是否有可能以某种方式配置python模块或REPL以对所有定义的类使用默认元类,而不管类中是否使用了元类?
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'
答案 0 :(得分:3)
使用Pavel Anossov(现已删除)评论:
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)
打印
test_value
请注意,一个类只能有一个元类。 (毕竟,任何对象都只能有一种类型)。但另外,类的元类必须是其所有基类的元类的(非严格)子类。换句话说,类的元类和其所有基类的元类必须相同,或者所有这些元类必须是彼此的子类。因此,如果类尝试使用不是met
的子类的元类,则上述解决方案可能无效。
例如,
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
加注
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
答案 1 :(得分:2)
在python 2.x上你可以做到
__metaclass__ = met
在模块的开头,然后在旧样式模式下定义您的类:
class A:
pass
在3.x上,这已不再可能。此外,“明确比隐含更好。”
另一种方法,你可以这样做:
class Object(metaclass=met): # Py3k syntax
pass
并且始终从中继承。
注意:调用type
的子类是使用与Py2k和Py3k兼容的元类的唯一方法。就像unutbu的答案一样