was/is 那个 "void* <unused>" 论点是为了什么,一些 __sizeof__ 方法在 CPython 中有什么?
What was/is that "void* <unused>" argument for, that some __sizeof__ methods have in CPython?
CPython 源代码中的几个 C 类型有一个 __sizeof__
方法,因此它们可以为具有 sys.getsizeof
的实例提供大致准确的大小(以字节为单位)。
这些方法被声明为 METH_NOARG
但有些方法确实有一个 void* whatever
参数,例如 itertools.product.__sizeof__
:
static PyObject *
product_sizeof(productobject *lz, void *unused)
{
Py_ssize_t res;
res = _PyObject_SIZE(Py_TYPE(lz));
res += PyTuple_GET_SIZE(lz->pools) * sizeof(Py_ssize_t);
return PyLong_FromSsize_t(res);
}
static PyMethodDef product_methods[] = {
/* ... */
{"__sizeof__", (PyCFunction)product_sizeof, METH_NOARGS, sizeof_doc},
{NULL, NULL} /* sentinel */
};
有些人有(例如1, 2), while others don't (for example: 1, 2)。当你声明一个没有参数的方法时,有一个参数似乎没有意义。
鉴于名称 "unused",它似乎曾经有过某种意义,但我不明白是什么意思。我试过使用 "git blame" 并阅读了一些相关问题,但找不到与此 "unused" 论点相关的任何内容。我还认为它可能与 sys.getsizeof
的 "default" 参数有关,但它没有传递给方法 - 方法知道给出的默认值有什么意义...
我对此很感兴趣:争论的目的是什么(以及当它变得过时时为什么不将其删除)。
根据 Martijn Pieters 的评论,我能够找出为什么这些方法有第二个参数。没有列出的那些在参数诊所文件中有一个包装函数(所以它只是 "hidden")。它不仅与 __sizeof__
相关,而且与所有 METH_NOARG
方法相关。
METH_NOARGS
Methods without parameters don’t need to check whether arguments are given if they are listed with the METH_NOARGS
flag. They need to be of type PyCFunction
. The first parameter is typically named self and will hold a reference to the module or object instance. In all cases the second parameter will be NULL.
但是 PyCFunction
s 有两个参数:
PyCFunction
Type of the functions used to implement most Python callables in C. Functions of this type take two PyObject* parameters and return one such value. If the return value is NULL, an exception shall have been set. If not NULL, the return value is interpreted as the return value of the function as exposed in Python. The function must return a new reference.
(强调我的)
对应的typedef
可以在methodobject
中找到:
typedef PyObject *(*PyCFunction)(PyObject *, PyObject *);
所以在 PyMethodDef
中声明的所有方法都需要(至少)两个参数,即使它们不使用第二个参数。这就是它被称为 "unused" 的原因,它对方法本身没有任何意义。
没有只接受单个参数的特定类型的函数。 PyCFunction
s 始终采用两个作为其文档状态:
Type of the functions used to implement most Python callables in C. Functions of this type take two PyObject*
parameters and return one such value.
METH_NOARGS
的情况并不意味着该函数只有一个参数,而是意味着第二个参数将始终是 NULL
:
The first parameter is typically named self and will hold a reference to the module or object instance. In all cases the second parameter will be NULL
.
你也可以直接在调用的call.c:_PyMethodDef_RawFastCallKeywords
中看到这个:
case METH_NOARGS:
// After snipping checks away
result = (*meth) (self, NULL);
对此有很多讨论,请参阅 here, here
here 其中一些。
至于只有一个参数的版本,正如 Martijn 指出的那样,这些版本使用参数诊所来隐藏它。
CPython 源代码中的几个 C 类型有一个 __sizeof__
方法,因此它们可以为具有 sys.getsizeof
的实例提供大致准确的大小(以字节为单位)。
这些方法被声明为 METH_NOARG
但有些方法确实有一个 void* whatever
参数,例如 itertools.product.__sizeof__
:
static PyObject *
product_sizeof(productobject *lz, void *unused)
{
Py_ssize_t res;
res = _PyObject_SIZE(Py_TYPE(lz));
res += PyTuple_GET_SIZE(lz->pools) * sizeof(Py_ssize_t);
return PyLong_FromSsize_t(res);
}
static PyMethodDef product_methods[] = {
/* ... */
{"__sizeof__", (PyCFunction)product_sizeof, METH_NOARGS, sizeof_doc},
{NULL, NULL} /* sentinel */
};
有些人有(例如1, 2), while others don't (for example: 1, 2)。当你声明一个没有参数的方法时,有一个参数似乎没有意义。
鉴于名称 "unused",它似乎曾经有过某种意义,但我不明白是什么意思。我试过使用 "git blame" 并阅读了一些相关问题,但找不到与此 "unused" 论点相关的任何内容。我还认为它可能与 sys.getsizeof
的 "default" 参数有关,但它没有传递给方法 - 方法知道给出的默认值有什么意义...
我对此很感兴趣:争论的目的是什么(以及当它变得过时时为什么不将其删除)。
根据 Martijn Pieters 的评论,我能够找出为什么这些方法有第二个参数。没有列出的那些在参数诊所文件中有一个包装函数(所以它只是 "hidden")。它不仅与 __sizeof__
相关,而且与所有 METH_NOARG
方法相关。
METH_NOARGS
Methods without parameters don’t need to check whether arguments are given if they are listed with the
METH_NOARGS
flag. They need to be of typePyCFunction
. The first parameter is typically named self and will hold a reference to the module or object instance. In all cases the second parameter will be NULL.
但是 PyCFunction
s 有两个参数:
PyCFunction
Type of the functions used to implement most Python callables in C. Functions of this type take two PyObject* parameters and return one such value. If the return value is NULL, an exception shall have been set. If not NULL, the return value is interpreted as the return value of the function as exposed in Python. The function must return a new reference.
(强调我的)
对应的typedef
可以在methodobject
中找到:
typedef PyObject *(*PyCFunction)(PyObject *, PyObject *);
所以在 PyMethodDef
中声明的所有方法都需要(至少)两个参数,即使它们不使用第二个参数。这就是它被称为 "unused" 的原因,它对方法本身没有任何意义。
没有只接受单个参数的特定类型的函数。 PyCFunction
s 始终采用两个作为其文档状态:
Type of the functions used to implement most Python callables in C. Functions of this type take two
PyObject*
parameters and return one such value.
METH_NOARGS
的情况并不意味着该函数只有一个参数,而是意味着第二个参数将始终是 NULL
:
The first parameter is typically named self and will hold a reference to the module or object instance. In all cases the second parameter will be
NULL
.
你也可以直接在调用的call.c:_PyMethodDef_RawFastCallKeywords
中看到这个:
case METH_NOARGS:
// After snipping checks away
result = (*meth) (self, NULL);
对此有很多讨论,请参阅 here, here here 其中一些。
至于只有一个参数的版本,正如 Martijn 指出的那样,这些版本使用参数诊所来隐藏它。