noob question: "TypeError" wrong number of args

Edward Elliott nobody at 127.0.0.1
Tue May 2 15:53:58 EDT 2006


bruno at modulix wrote:
> It is to be taken literally. Either you talk about how Python
> effectively works or the whole discussion is useless.

I started talking about the code-level view (programmer's perspective) so
shorthand was fine.  Now that we've moved on to interpreter/compiler-level
stuff, I agree that more precision is warranted.

> You skipped the interesting part, so I repost it and ask again: how
> could the following code work without the instance being an explicit
> parameter of the function to be used as a method ?
> 
> def someFunc(obj):
>   try:
>     print obj.name
>   except AttributeError:
>     print "obj %s has no name" % obj
> 
> import types
> m = MyObj('parrot')
> m.someMeth = types.MethodType(someFunc, obj, obj.__class__)
> m.someMeth()

I posted the only part that needs modification.  Here it is again with the
entire segment:

class MyObj(object):
  def __init__(name):
    self.name = name  <== interpreter binds name 'self' to object instance.
                          compiler adds 'self' to method sig as 1st param.

def someFunc(obj):
  try:
    print obj.name  <== 'obj' gets bound to first arg passed.  when bound 
                        as a method, first arg will be object instance.
                        when called as func, it will be first actual arg.
  except AttributeError:
    print "obj %s has no name" % obj

import types
m = MyObj('parrot')
m.someMeth = types.MethodType(someFunc, obj, obj.__class__)  <== binds obj 
                                   to first parameter of someFunc as usual
m.someMeth()

 
> You see, wrapping a function into a method is not done at compile-time,
> but at runtime. And it can be done manually outside a class statement.
> In the above example, someFunc() can be used as a plain function.

All the parameter information has been preserved.  Method signatures are
unchanged from their current form, so the interpreter has no trouble
deducing arguments.  You just don't actually declare self yourself.  When
binding a function to an object as above, the interpreter sees and does
exactly the same thing as now.

> This
> wouldn't work with some automagical injection of the instance in the
> function's local namespace, because you would then have to write
> "method"'s code diffently from function's code.

Maybe this will make it clearer:

Programmer's view     Compiler                           Interpreter's view
def func (a, b)       func (a, b) -> func (a, b)         func (a, b)
def method (a)        method (a) -> method (self, a)     method (self, a)

IOW the compiler adds 'self' to the front of the parameter list when
processing a method declaration.  Interpreter sees the same signature as
now, only programmer doesn't have to write 'self' anymore.

>> And the rest should work fine.  When the interpreter sees a method
>> declaration,
> 
> The interpreter never sees a 'method declaration', since there is no
> such thing as a 'method declaration' in Python. The def statement
> creates a *function* object:

Fine, whatever, compiler sees method declaration, interpreter sees function
object.  The point is, the interpreter sees the same thing it does now.

>> Complete non-sequitor, what does this have to do with self?
> 
> It has to do that the obj.name() syntax doesn't imply a *method* call -
> it can as well be a plain function call. 

Ok I see your point, but it doesn't matter because the interpreter sees the
same function object as before.

This confusion is partly (mostly? ;) my fault.  I haven't been
distinguishing precisely between the interpreter and the compiler because
usually with Python it doesn't matter (in practice).  This is clearly one
place it does.  In the words of Douglas Adams: We apologize for the
inconvenience.


> Also, and FWIW: 
>>>> def moduleFunc():
> ...     print self.name
> ...
>>>> moduleFunc()
> Traceback (most recent call last):
> NameError: global name 'self' is not defined

Exactly, that was my point in the first place.




More information about the Python-list mailing list