Python与abstractmethod的不同行为

won*_*ng2 4 python abstract-class abc

我有两个继承自同一父级的类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
Run Code Online (Sandbox Code Playgroud)

唯一的区别是,D从继承tupleP同时C继承了P而已.

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

TypeError: Can't instantiate abstract class C with abstract methods foo
Run Code Online (Sandbox Code Playgroud)

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

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

Mar*_*ers 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
Run Code Online (Sandbox Code Playgroud)