在Python 2中,通过一个技巧,可以创建一个具有多个基类的类,尽管基类具有不是彼此子类的元类。
诀窍是这些元类本身有一个元类(将其命名为“元元类”),并且此元元类为元类提供一个调用方法,该方法可以在必要时动态创建基本元类的公共子元类。最终,生成一个类,其元类是新的子元类。这是代码:
>>> class MetaMeta(type):
... def __call__(mcls, name, bases, methods):
... metabases = set(type(X) for X in bases)
... metabases.add(mcls)
... if len(metabases) > 1:
... mcls = type(''.join([X.__name__ for X in metabases]), tuple(metabases), {})
... return mcls.__new__(mcls, name, bases, methods)
...
>>> class Meta1(type):
... __metaclass__ = MetaMeta
...
>>> class Meta2(type):
... __metaclass__ = MetaMeta
...
>>> class C1:
... __metaclass__ = Meta1
...
>>> class C2:
... __metaclass__ = Meta2
...
>>> type(C1)
<class '__main__.Meta1'>
>>> type(C2)
<class '__main__.Meta2'>
>>> class C3(C1,C2): pass
...
>>> type(C3)
<class '__main__.Meta1Meta2'>
Run Code Online (Sandbox Code Playgroud)
这个例子(当然将语法更改为class C1(metaclass=Meta1)etc)在Python 3中不起作用。
问题 1:我是否正确理解,在 Python 2 中,C3使用第一个基数的元类构造 first ,并且只有在type(C3)不是type(C1)和 的公共子类时才会产生错误type(C2),而在 Python 3 中错误是更早引发的?
问题 2:(如何)可以使上面的示例在 Python 3 中运行吗?我确实尝试使用abc.ABCMetaas metametaclass 的子类,但即使使用自定义__subclasscheck__make issubclass(Meta1, Meta2)return True,创建 C3 仍然会导致错误。
注意:当然,我可以通过静态定义Meta1Meta2并显式使用Python 3 作为C3. 然而,这不是我想要的。我希望动态创建公共子元类。
下面的示例显示了 python3.x 中的一些选项。具体来说,C3有一个动态创建的元类,但在很多方面都是显式创建的。 C4有一个在其元类函数中动态创建的元类。 C5只是为了证明它也具有相同的元类属性C4。(我们并没有因为继承而丢失任何东西,如果您使用函数作为元类而不是...,则可能会type发生这种情况)
class Meta1(type):
def foo(cls):
print(cls)
class Meta2(type):
def bar(cls):
print(cls)
class C1(object, metaclass=Meta1):
"""C1"""
class C2(object, metaclass=Meta2):
"""C2"""
class C3(C1, C2, metaclass=type('Meta3', (Meta1, Meta2), {})):
"""C3"""
def meta_mixer(name, bases, dct):
cls = type('MixedMeta', tuple(type(b) for b in bases), dct)
return cls(name, bases, dct)
class C4(C1, C2, metaclass=meta_mixer):
"""C4"""
C1.foo()
C2.bar()
C3.foo()
C3.bar()
C4.foo()
C4.bar()
class C5(C4):
"""C5"""
C5.foo()
C5.bar()
Run Code Online (Sandbox Code Playgroud)
应该指出的是,我们在这里玩火(与您在原始示例中玩火的方式相同)。不能保证元类在协作多重继承中能够很好地发挥作用。如果它们不是为此设计的,那么您很可能在使用它时会遇到错误。如果它们是为此而设计的,那么就没有理由进行这种黑客运行时混合:-)。
| 归档时间: |
|
| 查看次数: |
4340 次 |
| 最近记录: |