Jp Calderone <[EMAIL PROTECTED]> writes: > When the class object is created, the namespace is scanned for > instances of <type 'function'>. For those and only those, a > descriptor is created which will produce bound and unbound methods.
This isn't quite correct. A descriptior is any object which has callable attributes called "__get__", "__set__" or "__delete__". Pure Python functions *are* descriptors: >>> import types >>> for name in '__get__', '__set__', '__delete__': ... print name, name in dir(types.FunctionType) ... __get__ True __set__ False __delete__ False because they have a __get__ attribute. Builtin functions are not descriptors: >>> for name in '__get__', '__set__', '__delete__': ... print name, name in dir(types.BuiltinFunctionType) ... __get__ False __set__ False __delete__ False because they do not have any of these. It is the FunctionType.__get__ which is responsible for the binding of methods. You can see this for yourself by calling it directly: >>> class Foo(object): ... pass ... >>> def bar(): ... pass ... >>> bar.__get__(None, Foo) <unbound method Foo.bar> >>> bar.__get__(Foo(), Foo) <bound method Foo.bar of <__main__.Foo object at 0x40171a6c>> Note that if FunctionType.__get__ is passed both an instance and a class, then it returns a bound method. If it is only passed a class, then it returns an unbound method. So, let's write a little descriptior which merely reports what arguments it's __get__ method receives: >>> class Test__get__(object): ... def __get__(*args): ... return args ... Let's add an instance of this as a class attribute to Foo: >>> Foo.test = Test__get__() ... and see what happens when you access it through the class: >>> Foo.test (<__main__.Test__get__ object at 0x40171b8c>, None, <class '__main__.Foo'>) ... and what happens when you access it via an instance of the class: >>> Foo().test (<__main__.Test__get__ object at 0x40171b8c>, <__main__.Foo object at 0x40171a4c>, <class '__main__.Foo'>) Observe that when accessing the attribute through the class, __get__ is not passed any instance, which tells __get__ to return an unbound method (as we saw above). If it is accessed through an instance, __get__ is passed both an instance and its class, which tells __get__ to return a bound method. The question remains "Why is __get__ called when an attribute is looked up?" The answer is "Because that's what __getattribute__ does". Which __getattribute__? That depends. If you access via the class, then it's type.__getattribute__, if you access through an instance of the class, then it's object.__getattribute__. More generally, an attribute access such as X.Y is equivalent to type(X).__getattribute__('Y') So, the type of object whose attribute you are looking up, determines (via it's __getattribute__ method) the arguments that the attribute's __get__ will be passed. Note that __getattribute__ of ModuleType, does *not* invoke this descriptor protocol of functions at all ... otherwise, all module-level functions would be turned into methods ! -- http://mail.python.org/mailman/listinfo/python-list