4

我有两个类从同一个父类继承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继承自tuplePwhile仅C继承自P

现在这是行为:c = C()出现错误,如预期的那样:

TypeError: Can't instantiate abstract class C with abstract methods foo

d = D()工作没有错误!

我什至可以打电话d.foo()。我该如何解释这种行为?

4

1 回答 1

8

在方法中测试抽象方法object.__new__;当您继承 from 时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
于 2014-07-28T07:55:02.653 回答