Referring to class methods in class attributes

mk mrkafk at gmail.com
Thu Feb 18 13:47:23 CET 2010


Bruno Desthuilliers wrote:
>> Thanks, that worked. But in order to make it work I had to get rid of
>> 'self' in print_internal_date signature
> 
> Indeed. Using it that way, the print_internal_date will not be wrapped
> in a method object.

Hold on! How does Python know what to wrap and what not to wrap, 
assuming of course programmer doesn't use @classmethod or @staticmethod? 
Bc self has no special significance, it's just a (strong) convention, 
Python can't know what's the first argument of a function supposed to 
be, self or regular argument, and therefore it has no way of 
differentiating between functions (defined in class body) designed to 
become methods and those that are not?

Where can I read on Python internals like this (aside from post of 
yours, that is)? Bc  frankly skimming http://docs.python.org/reference/ 
didn't give me impression that a lot on the subject is there (well 
there's some, I found smth akin to your explanation below, although 
yours is way more readable)?

Thanks for explanation below -- I'm going to ask some related questions.

> Mmmm... Let's try to explain the whole damn thing. It's really (and IMHO
> beautifully) simple once you get it, but I agree it's a bit peculiar
> when compared to most mainstream OO languages.
> 
> The first thing is that the def statement *always* yield a function
> object. Always. If you don't believe it, try the following snippet:
> 
> class Foo(object):
>     def bar(self):
>         return "baaz"
> 
> print Foo.__dict__.keys()
> print type(Foo.__dict__['bar'])

Just one thing here:

 >>> Foo.bar
<unbound method Foo.bar>

Huh?! Why does it say 'unbound' method? Shouldn't that be bound method 
(bound to Foo, that is)?

> So, why is it that type(Foo.bar) != type(Foo.__dict__['bar']) ?

 >>> type(Foo.__dict__['bar'])
<type 'function'>
 >>> type(Foo.bar)
<type 'instancemethod'>

instancemethod - now that's something new.


> The
> answer is : attribute lookup rules and the descriptor protocol.
> 
> To make a long story short, the descriptor protocol specify that, when,
> during an attribute lookup, a name resolves to a class attribute AND
> this attribute has a __get__ method, then this __get__ method is called
>  (with either the instance or None and the class itself as arguments)

Depending, I assume, on whether this is instance call | class method 
call, respectively?

Hmm why does the __get__ receive class as argument on top of instance | 
None? After all, when having an instance, the class can always be found 
by instance.__class__ ? Is this for sake of class methods?

Python is science, I gather: an answer to one question bears another 10 
questions.

> and whatever it returns becomes the result of the attribute lookup. This
> mechanism is what provides support for computed attributes.
> 
> Now the trick is that the function type do implement the descriptor
> protocol. So when a function is an attribute of a class object and you
> try to access it as an attribute of either the class itself or an
> instance of the class, it's __get__ method is called with the instance
> (or None) and the class. 

> Having access to itself (of course),

Quick question: how does a function access itself? Aside from rejected 
PEP (http://www.python.org/dev/peps/pep-3130/) I don't see the way of 
accessing itself outside globals() (and even then how would a function 
know its name -- well it shouldn't care about it really, as function 
object doesn't care how it's labelled, right?). Or does in "real Python" 
func's __get__ receive its own function (func) as an argument, like in 
your example implementation below?

> the
> instance (if there's one) and the class, it's easy for it to wrap all
> this into a method object. Which is itself a callable object, that when
> called mostly inject the instance as first object in the argument's list
> and returns the result of calling the wrapped function object.

Aha! So that's the mechanism that makes self magically appear in an 
argument list! I always wondered how it worked. !!THANKS!!


> My 2 cents...

Well, Bruno -- that was more like $200!

Regards,
mk




More information about the Python-list mailing list