[pypy-dev] fun with functions

Armin Rigo arigo at tunes.org
Fri Jun 25 18:18:18 CEST 2004


Hello,

I'm reworking argument dispatching code, and I realize that we've always had a
funny problem.  In CPython, we have the following half-expected behavior:

   class X:
     def f(self, **kwds):
       print kwds
   x = X()
   x.f(v=5)     ->  {'v': 5}
   x.f(self=5)  ->  TypeError: multiple values for argument 'self'

But of course, nothing wrong with:

   def f(**kwds):
     print kwds
   f(self=5)   ->  {'self': 5}

However, this fails in PyPy with the same TypeError as above!  The reason is
that the call is done via the __call__ descriptor, which is a perfectly normal
method:

   f.__call__   ->  <method object at 0xe75fcac>

(In CPython you get a <method-wrapper object>.)

Now if it is a method we can investiate a bit:

   >>> f.__call__.im_self is f
   True
   >>> f.__call__.im_func
   <function object at 0xe73440c>
   >>> f.__call__.im_func.func_code
   <internal-code object at 0xe5fc98c>
   >>> f.__call__.im_func.func_code.co_varnames
   AttributeError: co_varnames

but actually, even without (yet) exposing it at app-level, the code object has
got a signature which says the function's argument list is (self, *args,
**keywords).  The name 'self' conflicts here with a 'self' keyword.

Ack.  It's nice and all to be able to inspect built-in functions' signature
(which you cannot do yet, but it's just a matter of adding computed co_xxx
attributes on this <internal-code object>)... but this is a problem.

Moreover, we have a different compatibility problem too: in CPython, built-in
functions don't have a __get__, so you can put them in classes and read them
out without having the first argument bound to the instance.  For example, if
you put 'operator.add' in the class TrivialObjSpace, then 'space.add' is
exactly 'operator.add' and not a bound version of it.

What should we do about it?  Maybe asking python-dev for guidance?  Have
'unboundable function objects' -- like staticmethod, but the latter is not
callable -- and make some carefully selected functions unboundable for
compatibility?

For the 1st problem we could force a general solution by saying that the
argument that a method binds is hidden to keywords.  It would also make the
very first example of this e-mail work, although it doesn't work in CPython.


A bientot,

Armin.



More information about the Pypy-dev mailing list