Edward Elliott a écrit : > bruno at modulix wrote: > (snip) > >>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.
Nope. > 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. In this exemple, it was named 'obj', to make clear that there was nothing special about 'self'. As you can see from the call, I didn't actually passed the fist param, since the method wrapper takes care of it... So if we were to implement your proposition (which seems very unlikely...), the above code *would not work* - we'd get a TypeError because of the missing argument. > When > binding a function to an object as above, the interpreter sees and does > exactly the same thing as now. I'm sorry, but you're just plain wrong. *Please* take time to read about the descriptor protocol and understand Python's object model. > >>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. 1/ there is *no* 'method declaration' in Python 2/ wrapping functions into methods happens at runtime, *not* at compile time. (snip) >>>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, There ain't *nothing* like a 'method declaration' in Python. Zilch, nada, none, rien... All there is is the def statement that creates a *function* (and the class statement that creates a class object). > >>>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, Not quite, I'm afraid. > >>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. I'm afraid we don't understand each other here. This was supposed to come as an illustration that, if some black magic was to 'inject' the instance (here named 'self') in the local namespace of a 'method' (the way you see it), we would loose the possibility to turn a function into a method. Try to re-read both examples with s/obj/self/ in the first one and s/self/obj/ in this last one. Edward, I know I told you so at least three times, but really, seriously, do *yourself* a favor : take time to read about descriptors and metaclasses - and if possible to experiment a bit - so you can get a better understanding of Python's object model. Then I'll be happy to continue this discussion (. FWIW, I too found at first that having to explicitely declare the instance as first param of a 'function-to-be-used-as-a-method' was an awful wart. And by that time (Python 1.5.2), it actually *was* a wart IMVHO - just like the whole 'old-style-class' stuff should I say. But since 'type-unification' and new-style-classes, the wart has turned into a feature, even if this only become obvious once you get a good enough understanding of how the whole damn thing works. Following it's overall design philosophy, Python exposes (and so let you take control of) almost any detail of the object model implementation. The purpose here is to make simple things simple *and* complex things possibles, and the mean is to have a restricted yet consistent set of mechanisms. It may not be a jewel of pure beauty, but from a practical POV, it ends up being more powerful than what you'll find in most main-stream OOPLs - where simple things happens to be not so simple and complex things sometime almost impossible - and yet much more usable than some more powerful but somewhat cryptic OOPLs (like Common Lisp - which is probably the most astonishing language ever) where almost anything is possible but even the simplest things tend to be complex. Oh, also - should I mention it here ? - Ruby is another pretty nice and powerful OOPL, with a more 'pure' object model (at least at first sight - I have not enough experience with it to know if it holds its promises). While Python is My Favourite Language(tm), I'm not too much religious about this, and can well understand that someone's feature is someone else's wart - thanks the Lord, everyone is different and unique -, and you may feel better with Ruby. -- http://mail.python.org/mailman/listinfo/python-list