Metaclasses are not called in subclasses. What did I wrong?

  • Thread starter =?iso-8859-2?B?TOl0ZXr1?=
  • Start date
?

=?iso-8859-2?B?TOl0ZXr1?=

I use Python 2.4.4. Please read the code below:

-----------------------------------------------------------
from new import classobj

def mymeta(name,bases,clsdict):
print 'meta: %s'%name
return classobj(name,bases,clsdict)

class A(object):
__metaclass__=mymeta

class B(A):
pass

-----------------------------------------------------------

This should print

meta: A
meta: B

when classes A and B are created. But only meta: B is missing,
since mymeta() is not called when class B is created.

Related python documentation states that mymeta() must be called when B is
created, since metaclasses are looked up in bases classes if not found in
the dictionary of the class itself.
From Python 2.4.4's manual: "Otherwise, if there is at least one base class,
its metaclass is used (this looks for a __class__ attribute first and if not
found, uses its type)."

Thanks for your help.

Viktor
 
P

Peter Otten

Létez? said:
I use Python 2.4.4. Please read the code below:

-----------------------------------------------------------
from new import classobj

def mymeta(name,bases,clsdict):
print 'meta: %s'%name
return classobj(name,bases,clsdict)

mymeta is not a class.
class A(object):
__metaclass__=mymeta

Throw in

print "A.__class__", A.__class__

here and read the sentence from the manual again: The __class__ is 'type',
so no print... side effects are to be expected below.
class B(A):
pass

-----------------------------------------------------------

This should print

meta: A
meta: B

when classes A and B are created. But only meta: B is missing,
since mymeta() is not called when class B is created.

Related python documentation states that mymeta() must be called when B is
created, since metaclasses are looked up in bases classes if not found in
the dictionary of the class itself.

its metaclass is used (this looks for a __class__ attribute first and if
not found, uses its type)."

One way to get the output you expect:
.... def __init__(cls, name, bases, clsdict):
.... print "meta:", name
........ __metaclass__ = AType
....
meta: A....
meta: B

I tried with classobj first, but that didn't work:
....
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: Error when calling the metaclass bases
type 'classobj' is not an acceptable base type

Peter
 
G

Georg Brandl

Létezõ said:
I use Python 2.4.4. Please read the code below:

-----------------------------------------------------------
from new import classobj

def mymeta(name,bases,clsdict):
print 'meta: %s'%name
return classobj(name,bases,clsdict)

class A(object):
__metaclass__=mymeta

class B(A):
pass

-----------------------------------------------------------

This should print

meta: A
meta: B

when classes A and B are created. But only meta: B is missing,
since mymeta() is not called when class B is created.

Related python documentation states that mymeta() must be called when B is
created, since metaclasses are looked up in bases classes if not found in
the dictionary of the class itself.

its metaclass is used (this looks for a __class__ attribute first and if not
found, uses its type)."

Peter already explained that when __metaclass__ is not directly defined in the
class body, it's not used as the metaclass, but the class of the first base
class is.

This is an inconsistency IMHO, since Python normally respects inherited
attributes just like those defined in the class itself.

But well, you can live with it :)

Georg
 

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,769
Messages
2,569,582
Members
45,071
Latest member
MetabolicSolutionsKeto

Latest Threads

Top