Mixing abstract class and namedtuple

I want to define a mix-in from namedtuple and a base class with define and an abstract method :

import abc import collections class A(object): __metaclass__ = abc.ABCMeta @abc.abstractmethod def do(self): print("U Can't Touch This") B = collections.namedtuple('B', 'x, y') class C(B, A): pass c = C(x=3, y=4) print(c) c.do() 

From what I understand, after reading the documents and other examples that I saw , c.do() should raise an error, since the C class does not implement do() . However, when I run it ... it works:

 B(x=3, y=4) U Can't Touch This 

I have to ignore something.

+7
python
source share
1 answer

When you look at the resolution order of method C , you will see that B precedes A in this list. This means that when you instantiate C , the __new__ B method will be called first.

This is an implementation of namedtuple.__new__

 def __new__(_cls, {arg_list}): 'Create new instance of {typename}({arg_list})' return _tuple.__new__(_cls, ({arg_list})) 

You can see that it does not support shared inheritance because it breaks the chain and just calls the tuple __new__ method. Similarly, the ABCMeta.__new__ , which checks abstract methods , is never executed (wherever it is), and it cannot check abstract methods. Thus, instantiation is not interrupted.

I thought that inverting MRO would solve this problem, but it didn’t work out weirdly. I am going to research a little more and update this answer.

+5
source share

All Articles