为了找出传递给函数的参数是“临时”(只传递到函数中)还是在外部引用,我使用Py_REFCNT
。这是在一个C扩展包中完成的,但是为了更容易再现,我决定在这里提供一个基于ipythonmagic的Cython实现。在
在cpython3.5和cpython3.6之间,接受多个参数的函数(对于只接受一个参数的函数,它仍能正常工作)似乎发生了一些变化:
In [1]: %load_ext cython
In [2]: %%cython
...: cdef extern from "Python.h":
...: Py_ssize_t Py_REFCNT(object o)
...:
...: cpdef func(o, p):
...: return Py_REFCNT(o)
当我在3.5上运行代码时,它会给出预期的结果:
^{pr2}$但是在3.6版本中它给了我2
:
>>> import numpy as np
>>> func(np.ones(3), np.ones(3))
2
在评论中,有人问我关于C代码的问题,这里是:
static PyObject *
GetRefCount(PyObject *m, PyObject *args) {
if (PyTuple_CheckExact(args) && PyTuple_Size(args) > 0) {
Py_ssize_t reference_count = Py_REFCNT(PyTuple_GET_ITEM(args, 0));
return PyLong_FromSsize_t(reference_count);
}
PyErr_SetString(PyExc_TypeError, "wrong input");
return NULL;
}
方法定义:
{"getrefcount", /* ml_name */
(PyCFunction)GetRefCount, /* ml_meth */
METH_VARARGS, /* ml_flags */
"" /* ml_doc */
},
结果相同:
>>> import numpy as np
>>> getrefcount(np.ones(3)) # 3.5
1
>>> getrefcount(np.ones(3)) # 3.6
2
我想知道在3.6中引用计数在哪里(以及为什么)增加。我浏览了CPython源代码/Python问题跟踪程序,但没有找到答案。在
在Python3.5中,执行函数时,参数恰好从调用方堆栈中清除。在Python3.6中,参数碰巧仍然在调用方的堆栈中以及函数的参数元组中。在
在Python3.5上,函数调用通过here:
从堆栈中移除参数以构建参数元组:
^{pr2}$在3.6中,函数调用通过here:
经过here
^{4}$经过here:
经过here:
它将参数留在堆栈上,并使用对参数的新引用构建一个元组。在
相关问题 更多 >
编程相关推荐