After reading the excellent SO post, I tried crafting a module level metaclass:
def metaclass(future_class_name, future_class_parents, future_class_attrs):
print "module.__metaclass__"
future_class_attrs["bar"]="bar"
return type(future_class_name, future_class_parents, future_class_attrs)
__metaclass__=metaclass
class Foo(object):
def __init__(self):
print 'Foo.__init__'
f=Foo()
This doesn't work (i.e. "module.metaclass" doesn't get printed) unless I remove the object
base class of Foo. How come?
NOTE: I am using Python 2.6.1.
Inheriting from object automatically brings the type metaclass along with it. This overrides your module level __metaclass__ specification.
If the metaclass is specified at the class level, then object won't override it:
def metaclass(future_class_name, future_class_parents, future_class_attrs):
print "module.__metaclass__"
future_class_attrs["bar"]="bar"
return type(future_class_name, future_class_parents, future_class_attrs)
class Foo(object):
__metaclass__ = metaclass
def __init__(self):
print 'Foo.__init__'
f=Foo()
See http://docs.python.org/reference/datamodel.html?highlight=metaclass#customizing-class-creation
The specification specifies the order in which Python will look for a metaclass:
The appropriate metaclass is determined by the following precedence rules:
- If
dict['__metaclass__']
exists, it is used.- 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).- Otherwise, if a global variable named
__metaclass__
exists, it is used.- Otherwise, the old-style, classic metaclass (
types.ClassType
) is used.
You will see from the above that having a base class at all (whatever the base class is, even if it does not ultimately inherit from object
) pre-empts the module-level __metaclass__
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With