我有两个继承自同一个父P
的类:
from abc import ABCMeta, abstractmethod
class P(object):
__metaclass__ = ABCMeta
@abstractmethod
def foo(self):
pass
class C(P):
pass
class D(tuple, P):
pass
唯一的区别是D
继承自tuple
和P
而C
仅从P
继承。
现在这是行为:c = C()
错误,正如所料:
TypeError: Can't instantiate abstract class C with abstract methods foo
但d = D()
无误地运行!
我甚至可以致电d.foo()
。我该如何解释这种行为?
答案 0 :(得分:8)
在object.__new__
方法中测试抽象方法;当您从具有自己的tuple
方法的__new__
继承时,不会调用object.__new__
并且不会对抽象方法进行测试。
换句话说,将抽象方法与任何的内置不可变类型混合将导致此问题。
唯一有效的解决方案是在__new__
中进行自己的测试,然后只有在 tuple
之前放置抽象类时在子类中的两个碱基中混合。
class P(object):
__metaclass__ = ABCMeta
def __new__(cls, *args, **kwargs):
super_new = super(P, cls).__new__
if super_new.__self__ is not object:
# immutable mix-in used, test for abstract methods
if getattr(cls, '__abstractmethods__'):
raise TypeError(
"Can't instantiate abstract class %s "
"with abstract methods %s" % (
cls.__name__,
', '.join(sorted(cls.__abstractmethods__))))
return super_new(cls, *args, **kwargs)
@abstractmethod
def foo(self):
pass
class D(P, tuple):
pass