In a recent project I try to do something like this (more complex, but the same result):
class MetaA(type):
def __new__(cls, name, args, kwargs):
print kwargs["foo"]
return type.__new__(cls, name, args, kwargs)
class A(object):
__metaclass__ = MetaA
foo = "bar"
class B(A):
pass
I get this:
bar
Traceback (most recent call last):
File "C:\Users\Thorstein\Desktop\test.py", line 10, in <module>
class B(A):
File "C:\Users\Thorstein\Desktop\test.py", line 3, in __new__
print kwargs["foo"]
KeyError: 'foo'
Are class attributes not inherited? If so, is there any workaround possible in a similar framework to the above?
EDIT: Might be easier to see what I mean using an actual (simplified) example from the program..
class GameObjectMeta(type):
def __new__(cls, name, bases, attrs):
attrs["dark_color"] = darken(*attrs["color"])
return type.__new__(cls, name, bases, attrs)
class GameObject(object):
__metaclass__ = GameObjectMeta
color = (255,255,255) # RGB tuple
class Monster(GameObject):
pass
Basically, want to run a function on the base color to make a darker one that's saved in the class (multiple instances of the class will want the same color, but there will be a longer class hierarchy). I hope this'll make more sense..
It's not supposed to inherit those. The metaclass receives the attributes defined on the class it is instantiating, not those of its base classes. The whole point of the metaclass constructor is to get access to what is actually given in the class body.
In fact, the attributes of the base class really aren't "in" the subclass at all. It's not as if they are "copied" to the subclass when you define it, and in fact at creation time the subclass doesn't even "know" what attributes its superclasses might have. Rather, when you access B.foo
, Python first tries to find the attribute on B, then if it doesn't find it, looks on its superclasses. This happens dynamically every time you try to read such an attribute. The metaclass mechanism isn't supposed to have access to attributes of the superclass, because those really aren't there on the subclass.
A perhaps related problem is that your definition of __new__
is incorrect. The arguments to the metaclass __new__
are cls, name, bases, and attrs. The third argument is the list of base classes, not "args" (whatever you intend that to be). The fourth argument is the list of attributes define in the class body. If you want access to inherited attributes you can get at them via the bases.
Anyway, what are you trying to accomplish with this scheme? There's probably a better way to do it.
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