2

是否可以以某种方式配置 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'
4

2 回答 2

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
于 2013-07-05T02:52:32.137 回答
2

在 python 2.x 上,你可以这样做

 __metaclass__ = met

在模块的开头,然后以旧样式模式定义您的类:

class A:
    pass

在 3.x 上,这不再可能。此外,“显式优于隐式”。

另一种方法,你可以这样做:

class Object(metaclass=met):  # Py3k syntax
    pass

并始终从中继承。

注意:调用的子类type是使用与 Py2k 和 Py3k 兼容的元类的唯一方法。就像在unutbu的回答中一样

于 2013-07-05T02:48:21.703 回答