A newbie metaclass question

C

could ildg

When I try to learn metaclass of python by article at this place:
http://www.python.org/2.2/descrintro.html#metaclasses,
I changed the autosuper example a little as below:
<code>
class autosuper(type):
def __init__(cls,name,bases,dict):
super(autosuper,cls).__init__(name,bases,dict)
setattr(cls,"_%s__super" % name, super(cls))
print "in metaclass: ", super(cls)

class A:
__metaclass__ = autosuper
def meth(self):
print "in class A: ", self.__super

a=A()
a.meth()
</code>
The result is as below:
in metaclass: <super: <class 'A'>, NULL>
in class A: <super: <class 'A'>, <A object>>

The 2 line are not the same. Why? Is this because that instance a has not
been created when the __init__ of the metaclass is called? If the cls in the
__init__ method is not an instance of A, what is it?

The metaclass of python is kinda difficult for me. Thanks for your help.
 
P

Peter Otten

could said:
When I try to learn metaclass of python by article at this place:
http://www.python.org/2.2/descrintro.html#metaclasses,
I changed the autosuper example a little as below:
<code>
class autosuper(type):
def __init__(cls,name,bases,dict):
super(autosuper,cls).__init__(name,bases,dict)
setattr(cls,"_%s__super" % name, super(cls))
print "in metaclass: ", super(cls)

class A:
__metaclass__ = autosuper
def meth(self):
print "in class A: ", self.__super

a=A()
a.meth()
</code>
The result is as below:
in metaclass: <super: <class 'A'>, NULL>
in class A: <super: <class 'A'>, <A object>>

The 2 line are not the same. Why?

This particular difference has more to do with the descriptor protocol than
your custom metaclass. Instead of returning a class attribute unaltered, if
present, its __get__() method is called. E. g.:
.... pass
........ def __get__(self, *args):
.... print "args:", args
.... return 42
....args: (<__main__.A object at 0x402ad62c>, <class '__main__.A'>)
42

And now let's make sure:
True

a 'super' object has a __get__() method, and is therefore free to give you
back whatever it chooses to. (It can detect whether it's called by an
instance or a class by checking its first argument).

You might have found some hints in the text you quote, but a detailed
explanation is here:

http://users.rcn.com/python/download/Descriptor.htm
The metaclass of python is kinda difficult for me.

IIRC you were about to learn the OO basics just a few days ago. In that
situation I would put metaclasses _very_ low on my list of priorities.

Peter
 
S

Steven Bethard

could said:
When I try to learn metaclass of python by article at this place:
http://www.python.org/2.2/descrintro.html#metaclasses,
I changed the autosuper example a little as below:
<code>
class autosuper(type):
def __init__(cls,name,bases,dict):
super(autosuper,cls).__init__(name,bases,dict)
setattr(cls,"_%s__super" % name, super(cls))
print "in metaclass: ", super(cls)

class A:
__metaclass__ = autosuper
def meth(self):
print "in class A: ", self.__super

a=A()
a.meth()
</code>
The result is as below:
in metaclass: <super: <class 'A'>, NULL>
in class A: <super: <class 'A'>, <A object>>

The reason for this is that the super object is a descriptor. This
means that
self.__super
actually calls something like:
type(self).__super.__get__(self)
So the difference in the two is that the "in metaclass" print references
the unbound super object, and the "in class A" print references the
bound super object.

A very simple demonstration of this:

py> class C(object):
.... pass
....
py> C.sup = super(C)
py> C.sup
<super: <class 'C'>, NULL>
py> C().sup
<super: <class 'C'>, <C object>>
py> C.sup.__get__(C())
<super: <class 'C'>, <C object>>

Note that we get the "NULL" output when we ask the *class* for the "sup"
object. We get the "C object" output when we ask an *instance* for the
"sup" object. The example using __get__ is basically just the explicit
version of the one that doesn't use __get__.

HTH,

STeVe
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,009
Latest member
GidgetGamb

Latest Threads

Top