Python 不过,在这种情况下,它有很大的不同。令人惊讶的是,它确实有很大的不同。见@Mat哦,整洁。因此,由于函数给出的可能排序数大于置换数且不可被置换数整除,因此某些置换被过度表示。是的。为了简洁起见,我忽略了错误检查。当PyList_Size返回-1时,它并没有

Python 不过,在这种情况下,它有很大的不同。令人惊讶的是,它确实有很大的不同。见@Mat哦,整洁。因此,由于函数给出的可能排序数大于置换数且不可被置换数整除,因此某些置换被过度表示。是的。为了简洁起见,我忽略了错误检查。当PyList_Size返回-1时,它并没有,python,c++,python-3.x,python-c-api,python-c-extension,Python,C++,Python 3.x,Python C Api,Python C Extension,不过,在这种情况下,它有很大的不同。令人惊讶的是,它确实有很大的不同。见@Mat哦,整洁。因此,由于函数给出的可能排序数大于置换数且不可被置换数整除,因此某些置换被过度表示。是的。为了简洁起见,我忽略了错误检查。当PyList_Size返回-1时,它并没有失败,但当我正在研究如何传入参数时,它只是跳过了for循环。如果Py_ssize_t未签名,程序可能会崩溃,程序可能会失败,PyList_Size返回的-1表示抛出了异常,您必须有序地处理它,或者清除异常,或者将其转发-您只是没有满足代码中的适


不过,在这种情况下,它有很大的不同。令人惊讶的是,它确实有很大的不同。见@Mat哦,整洁。因此,由于函数给出的可能排序数大于置换数且不可被置换数整除,因此某些置换被过度表示。是的。为了简洁起见,我忽略了错误检查。当PyList_Size返回-1时,它并没有失败,但当我正在研究如何传入参数时,它只是跳过了for循环。如果Py_ssize_t未签名,程序可能会崩溃,程序可能会失败,
PyList_Size
返回的-1表示抛出了异常,您必须有序地处理它,或者清除异常,或者将其转发-您只是没有满足代码中的适当条件:DAh,哇,我错过了关于设置内部异常的部分。
>>>import evosutil
>>> a=[i for i in range(100)]
>>> evosutil.shuffle(a)
>>> a
[52, 66, 0, 58, 41, 18, 50, 37, 81, 43, 74, 49, 90, 20, 63, 32, 89, 60, 2, 44, 3, 80, 15, 24, 22, 69, 86, 31, 56, 68, 34, 13, 38, 26, 14, 91, 73, 79, 39, 65, 5, 75, 84, 55, 7, 53, 93, 42, 40, 9, 51, 82, 29, 30, 99, 64, 33, 97, 27, 11, 6, 67, 16, 94, 95, 62, 57, 17, 78, 77, 71, 98, 72, 8, 88, 36, 85, 59, 21, 96, 23, 46, 10, 12, 48, 83, 4, 92, 45, 54, 1, 25, 19, 70, 35, 61, 47, 28, 87, 76]
>>> (Ctrl-D)
*** Error in `python3': free(): invalid next size (fast): 0x083fe680 ***
*** Error in `python3': munmap_chunk(): invalid pointer: 0x083ff0e0 ***
Segmentation fault (core dumped)
inline void _List_SwapItems(PyObject* list, Py_ssize_t i1, Py_ssize_t i2){
    PyObject* tmp=PyList_GetItem(list, i2);
    PyList_SetItem(list, i2, PyList_GetItem(list, i1));
    PyList_SetItem(list, i1, tmp);
}

//Naive Fisher–Yates shuffle
static PyObject* shuffle(PyObject* self, PyObject* args){
    PyObject* list;
    PyArg_ParseTuple(args,"O", &list);
    unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
    std::minstd_rand0 rand(seed);
    Py_ssize_t size = PyList_Size(list);
    for(int i=0; i<size;++i){
        int randIndex = rand()%size;
        _List_SwapItems(list, randIndex, i);
    }
    Py_RETURN_NONE;
}
inline void _List_SwapItems(PyObject* list, Py_ssize_t i1, Py_ssize_t i2){
    if (i1 == i2) {
        return;
    }
    PyObject* obj1=PyList_GetItem(list, i1);
    PyObject* obj2=PyList_GetItem(list, i2);
    Py_XINCREF(obj1);
    Py_XINCREF(obj2);
    PyList_SetItem(list, i2, obj1);
    PyList_SetItem(list, i1, obj2);
}
inline void _List_SwapItems(PyObject* list, Py_ssize_t i1, Py_ssize_t i2){
    PyObject* tmp = PyList_GET_ITEM(list, i2);
    PyList_SET_ITEM(list, i2, PyList_GET_ITEM(list, i1));
    PyList_SET_ITEM(list, i1, tmp);
}
static PyObject* shuffle(PyObject* self, PyObject* args){
    PyObject* list;
    if (! PyArg_ParseTuple(args, "O", &list)) {
        // PyArg_ParseTuple set the proper exception
        return NULL;
    }

    if (! PyList_Check(list)) {
        PyErr_SetString(PyExc_TypeError,
            "bad argument to shuffle; list expected");
        return NULL;
    }

    unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
    std::minstd_rand0 rand(seed);

    Py_ssize_t size = PyList_Size(list);
    for(int i=0; i<size;++i){
        int randIndex = rand()%size;
        _List_SwapItems(list, randIndex, i);
    }
    Py_RETURN_NONE;
}