[Python-Dev] Special-casing "O"

M.-A. Lemburg mal@lemburg.com
Mon, 28 May 2001 11:19:16 +0200


Tim Peters wrote:
> 
> [Thomas Wouters]
> > And don't forget the method-specific errormessage by passing ':len' in
> > the format string. Of course, this can easily be (and probably should)
> > done by passing another argument to whatever parses arguments in
> > METH_O, rather than invoking string parsing magic every call.
> 
> Martin's patch automatically inserts the name of the function in the
> TypeError it raises when a METH_O call doesn't get exactly one argument, or
> gets a (one or more) keyword argument.
> 
> Stick to METH_O and it's a clear win, even in this respect:  there's no info
> in an explicit ":len" he's not already deducing, and almost all instances of
> "O:name" formats today are exactly the same this way:
> 
> if (!PyArg_ParseTuple(args, "O:abs", &v))
> if (!PyArg_ParseTuple(args, "O:callable", &v))
> if (!PyArg_ParseTuple(args, "O:id", &v))
> if (!PyArg_ParseTuple(args, "O:hash", &v))
> if (!PyArg_ParseTuple(args, "O:hex", &v))
> if (!PyArg_ParseTuple(args, "O:float", &v))
> if (!PyArg_ParseTuple(args, "O:len", &v))
> if (!PyArg_ParseTuple(args, "O:list", &v))
> else if (!PyArg_ParseTuple(args, "O:min/max", &v))
> if (!PyArg_ParseTuple(args, "O:oct", &v))
> if (!PyArg_ParseTuple(args, "O:ord", &obj))
> if (!PyArg_ParseTuple(args, "O:reload", &v))
> if (!PyArg_ParseTuple(args, "O:repr", &v))
> if (!PyArg_ParseTuple(args, "O:str", &v))
> if (!PyArg_ParseTuple(args, "O:tuple", &v))
> if (!PyArg_ParseTuple(args, "O:type", &v))
> 
> Those are all the ones in bltinmodule.c, and nearly all of them are called
> extremely frequently in *some* programs.  The only oddball is min/max, but
> then it supports more than one call-list format and so isn't a METH_O
> candidate anyway.  Indeed, Martin's patch gives a *better* message than we
> get for some mistakes today:
> 
> >>> len(val=2)
> Yraceback (most recent call last):
>  File "<stdin>", line 1, in ?
> TypeError: len() takes exactly 1 argument (0 given)
> >>>
> 
> Martin's would say
> 
>     TypeError: len takes no keyword arguments
> 
> in this case.  He should add "()" after the function name.  He should also
> throw away the half of the patch complicating and slowing METH_O to get some
> theoretical speedup in other cases:  make the one-arg builtins fly just as
> fast as humanly possible.

If we end up only optimizing the re.match("O+") case, we wouldn't need 
the METH_SPECIAL masks; a simple METH_OBJARGS flag would do the trick
and Martin could call the underlying API with one or more PyObject*
taken directly from the Python VM stack.

In that case, please consider at least supporting "O", "OO" and "OOO"
with optional arguments treated like I suggested in an earlier
posting (simply pass NULL and let the API take care of assigning
a default value).

This would take care of most builtins:

Python/bltinmodule.c:
--      if (!PyArg_ParseTuple(args, "OO:filter", &func, &seq))
--      if (!PyArg_ParseTuple(args, "OO:cmp", &a, &b))
--      if (!PyArg_ParseTuple(args, "OO:coerce", &v, &w))
--      if (!PyArg_ParseTuple(args, "OO:divmod", &v, &w))
--      if (!PyArg_ParseTuple(args, "OO|O:getattr", &v, &name, &dflt))
--      if (!PyArg_ParseTuple(args, "OO:hasattr", &v, &name))
--      if (!PyArg_ParseTuple(args, "OOO:setattr", &v, &name, &value))
--      if (!PyArg_ParseTuple(args, "OO:delattr", &v, &name))
--      if (!PyArg_ParseTuple(args, "OO|O:pow", &v, &w, &z))
--      if (!PyArg_ParseTuple(args, "OO|O:reduce", &func, &seq, &result))
--      if (!PyArg_ParseTuple(args, "OO:isinstance", &inst, &cls))
--      if (!PyArg_ParseTuple(args, "OO:issubclass", &derived, &cls))
--      if (!PyArg_ParseTuple(args, "O:abs", &v))
--      if (!PyArg_ParseTuple(args, "O|OO:apply", &func, &alist, &kwdict))
--      if (!PyArg_ParseTuple(args, "O:callable", &v))
--      if (!PyArg_ParseTuple(args, "O|O:complex", &r, &i))
--      if (!PyArg_ParseTuple(args, "O:id", &v))
--      if (!PyArg_ParseTuple(args, "O:hash", &v))
--      if (!PyArg_ParseTuple(args, "O:hex", &v))
--      if (!PyArg_ParseTuple(args, "O:float", &v))
--      if (!PyArg_ParseTuple(args, "O|O:iter", &v, &w))
--      if (!PyArg_ParseTuple(args, "O:len", &v))
--      if (!PyArg_ParseTuple(args, "O:list", &v))
--      if (!PyArg_ParseTuple(args, "O|OO:slice", &start, &stop, &step))
--      else if (!PyArg_ParseTuple(args, "O:min/max", &v))
--      if (!PyArg_ParseTuple(args, "O:oct", &v))
--      if (!PyArg_ParseTuple(args, "O:ord", &obj))
--      if (!PyArg_ParseTuple(args, "O:reload", &v))
--      if (!PyArg_ParseTuple(args, "O:repr", &v))
--      if (!PyArg_ParseTuple(args, "O:str", &v))
--      if (!PyArg_ParseTuple(args, "O:tuple", &v))
--      if (!PyArg_ParseTuple(args, "O:type", &v))

-- 
Marc-Andre Lemburg
CEO eGenix.com Software GmbH
______________________________________________________________________
Company & Consulting:                           http://www.egenix.com/
Python Software:                        http://www.lemburg.com/python/