Reputation: 3098
Is it possible to somehow configure a python module or REPL to use a default metaclass for all classes defined, regardless of whether or not a metaclass is used in the class ?
class met(type):
def __init__(cls, name, bases, dct):
super(met, cls).__init__(name, bases, dct)
setattr(cls, "_test_member", "test_value")
class A(object):
pass
>>> A._test_member
'test_value'
Upvotes: 3
Views: 557
Reputation: 879471
Using Pavel Anossov's (now deleted) comment:
class met(type):
def __init__(cls, name, bases, dct):
super(met, cls).__init__(name, bases, dct)
cls._test_member = "test_value"
object = met('object', (object,), {})
class A(object):
pass
print(A._test_member)
prints
test_value
Note that a class can have only one metaclass. (Since, after all, any object can have only one type). But additionally, the metaclass of a class must be a (non-strict) subclass of the metaclasses of all its bases. In other words, the class's metaclass and the metaclasses of all its bases must either be the same, or all those metaclasses must be subclasses of each other. So the above solution may not work if a class tries to use a metaclass which is not a subclass of met
.
For example,
class met(type):
def __init__(cls, name, bases, dct):
super(met, cls).__init__(name, bases, dct)
cls._test_member = "test_value"
object = met('object', (object,), {})
class someothertype(type): pass
class B(object):
__metaclass__ = someothertype
raises
TypeError: Error when calling the metaclass bases
metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases
Upvotes: 4
Reputation: 33397
On python 2.x you could just do
__metaclass__ = met
in the beginning of the module and then define your class in old style mode:
class A:
pass
On 3.x, this is no longer possible. Also, "Explicit is better than implicit."
Another approach, you could do:
class Object(metaclass=met): # Py3k syntax
pass
and always inherit from it.
Note: Calling the subclass of type
is the only way to make use of metaclass compatible with both Py2k and Py3k. Like in unutbu's answer
Upvotes: 3