I was wondering what happens to methods declared on a metaclass. I expected that if you declare a method on a metaclass, it will end up being a classmethod, however, the behavior is different. Example
>>> class A(object):
... @classmethod
... def foo(cls):
... print "foo"
...
>>> a=A()
>>> a.foo()
foo
>>> A.foo()
foo
However, if I try to define a metaclass and give it a method foo, it seems to work the same for the class, not for the instance.
>>> class Meta(type):
... def foo(self):
... print "foo"
...
>>> class A(object):
... __metaclass__=Meta
... def __init__(self):
... print "hello"
...
>>>
>>> a=A()
hello
>>> A.foo()
foo
>>> a.foo()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'A' object has no attribute 'foo'
What’s going on here exactly ?
edit: bumping the question
You raise a good point.
Here is a good referenceto get a better understanding of the relations between objects, classes and metaclasses:
I also find this reference on descriptors to be quite enlightening about the mechanism of look-up in python.
But I can’t say I understand why
a.foofails whenA.foosucceeds. It seems that when you look up an attribute of an object, and python does not find it there, it does not exactly look up the attribute in the class, because if it did, it would findA.foo.EDIT:
Oh! I think I got it. It is due to how inheritance works. If you consider the schema provided by the above link, it looks like this:
Schematically, it boils down to:
Going left means going to the class of a given instance. Going up means going to the parent.
Now the inheritance mechanism makes the look-up mechanism make a right turn in the schema above. It goes
a → A → object. It must do so in order to follow the inheritance rule! To make it clear, the search path is:Then, clearly, the attribute
foowill not be found.When you lookup for the attribute
fooinA, however, it is found, because the lookup path is:It all makes sense when one thinks of how inheritance works.