[Python-Dev] Special-casing "O"
Tim Peters
tim.one@home.com
Sun, 27 May 2001 16:37:43 -0400
[Jeremy]
> How is METH_O different than METH_OLDARGS?
I have no idea: can you explain it? The #define's for these symbols are
uncommented, and it's a mystery to me what they're *supposed* to mean.
> The old-style argument passing is definitely the most efficient for
> functions of a zero or one arguments. There's special-case code in
> ceval to support it these cases -- fast_cfunction() -- primarily
> because in these cases the function can be invoked by using arguments
> directly from the Python stack instead of copying them to a tuple
> first.
OK, I'm looking in bltinmodule.c, at builtin_len. It starts like so:
static PyObject *
builtin_len(PyObject *self, PyObject *args)
{
PyObject *v;
long res;
if (!PyArg_ParseTuple(args, "O:len", &v))
return NULL;
So it's clearly expecting a tuple. But its entry in the builtin_methods[]
table is:
{"len", builtin_len, 1, len_doc},
That is, it says nothing about the calling convention. Since C fills in a 0
for missing values, and methodobject.c has
/* Flag passed to newmethodobject */
#define METH_OLDARGS 0x0000
#define METH_VARARGS 0x0001
#define METH_KEYWORDS 0x0002
then doesn't the stuct for builtin_len implicitly specify METH_OLDARGS? But
if that's true, and fast_cfunction() does not create a tuple in this case,
how is that builtin_len gets a tuple?
Something doesn't add up here. Or does it? There's no *reference* to
METH_OLDARGS anywhere in the code base other than its definition and its use
in method tables, so whatever code *keys* off it must be assuming a
hardcoded 0 value for it -- or indeed nothing keys off it at all.
I expect this line in ceval.c is doing the dirty assumption:
} else if (flags == 0) {
and should be testing against METH_OLDARGS instead.
But I see that builtin_len is falling into the METH_VARARGS case despite
that it wasn't declared that way and that it sure looks like METH_OLDARGS
(0) is the default. Confusing! Fix it <wink>.