I want to define a mix-in of a namedtuple and a base class with defines and 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 reading the docs and other examples I have seen, c.do()
should raise an error, as class C does not implement do()
. However, when I run it... it works:
B(x=3, y=4)
U Can't Touch This
I must be overlooking something.
In object-oriented programming, an abstract class is a class that cannot be instantiated.
An abstract class is a class, but not one you can create objects from directly. Its purpose is to define how other classes should look like, i.e. what methods and properties they are expected to have.
Yes, you have to implement all abstract methods in Python to instantiate them as objects (the ones marked with @abstractmethod , etc). How you implement these, however, are completely up to you. If you're not going to be instantiating, you don't need to override all of them.
ABCMeta metaclass provides a method called register method that can be invoked by its instance. By using this register method, any abstract base class can become an ancestor of any arbitrary concrete class.
When you take a look at the method resolution order of C
you see that B
comes before A
in that list. That means when you instantiate C
the __new__
method of B
will be called first.
This is the 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 cooperative inheritance, because it breaks the chain and simply calls tuple
s __new__
method. Like this the method that checks for abstract methods is never executed (where ever that is) and it can't check for abstract methods. So the instantiation does not fail.ABCMeta.__new__
I thought inverting the MRO would solve that problem, but it strangely did not. I'm gonna investigate a bit more and update this answer.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With