Reputation: 22623
I've been trying to learn about metaclasses in Python. I get the main idea, but I can't seem to activate the mechanism. As I understand it, you can specify M to be as the metaclass when constructing a class K by setting __metaclass__
to M at the global or class level. To test this out, I wrote the following program:
p = print
class M(type):
def __init__(*args):
type.__init__(*args)
print("The rain in Spain")
p(1)
class ClassMeta:
__metaclass__ = M
ClassMeta()
p(2)
__metaclass__ = M
class GlobalMeta: pass
GlobalMeta()
p(3)
M('NotMeta2', (), {})
p(4)
However, when I run it, I get the following output:
C:\Documents and Settings\Daniel Wong\Desktop>python --version Python 3.0.1 C:\Documents and Settings\Daniel Wong\Desktop>python meta.py 1 2 3 The rain in Spain 4
Shouldn't I see "The rain in Spain" after 1 and 2? What's going on here?
Upvotes: 7
Views: 831
Reputation: 229804
In Python 3 (which you are using) metaclasses are specified by a keyword parameter in the class definition:
class ClassMeta(metaclass=M):
pass
Specifying a __metaclass__
class property or global variable is old syntax from Python 2.x and not longer supported. See also "What's new in Python 3" and PEP 2115.
Upvotes: 14
Reputation: 11922
The syntax of metaclasses has changed in Python 3.0. The __metaclass__
attribute is no longer special at either the class nor the module level. To do what you're trying to do, you need to specify metaclass
as a keyword argument to the class
statement:
p = print
class M(type):
def __init__(*args):
type.__init__(*args)
print("The rain in Spain")
p(1)
class ClassMeta(metaclass=M): pass
Yields:
1
The rain in Spain
As you'd expect.
Upvotes: 2
Reputation: 882481
This works as you expect in Python 2.6 (and earlier), but in 3.0 metaclasses are specified differently:
class ArgMeta(metaclass=M): ...
Upvotes: 2