Python different behavior with abstractmethod

I have two classes inheriting from the same parent 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

The only difference is that it is Dinherited from tupleand P, while it is Cinherited only from P.

Now this behavior: c = C()got an error, as expected:

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

but it d = D()works without errors!

I can even call d.foo(). How can I explain this behavior?

+4
source share
1 answer

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
+8

All Articles