MSeifert MSeifert - 3 years ago 159
Python Question

What was/is that "void* <unused>" argument for, that some __sizeof__ methods have in CPython?

Several C types in the CPython source have a

__sizeof__
method so they can present approximately accurate sizes (in bytes) for instances with
sys.getsizeof
.

These methods are declared
METH_NOARG
but some do have a
void* whatever
argument, for example
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 */
};


Some have it (e.g. 1, 2), while others don't (for example: 1, 2). It doesn't seem to make sense to have an argument when you declare it a method without arguments.

Given the name "unused" it seems like it probably had some meaning once but I can't figure out for what. I've tried using "git blame" and reading through some of the related issues but couldn't find anything with respect to this "unused" argument. I also thought it may be related to the "default" argument for
sys.getsizeof
but that's not passed through to the method - and what would be the point for the method to know what default was given...

I'm interested it: What was the purpose of the argument (and when it became obsolete why wasn't it removed).

Answer Source

There's no specific type of function that only takes a single parameter, PyCFunctions always take two arguments as the documentation states.

The METH_NOARGS case doesn't mean that the function will only have a single parameter, rather, it means that the second parameter will always be 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.

you can also see this directly in call.c:

case METH_NOARGS:
    // After snipping checks away
    result = (*meth) (self, NULL);

There's a number of discussions covering this, see here, here and here for more.


As for the versions that only have a single argument, as Martijn points out, these use argument clinic to hide that.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download