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. -- http://mail.python.org/mailman/listinfo/python-list