当多重继承涉及内置类型时,Python3 ABCMeta会破坏契约

时间:2016-03-25 09:10:41

标签: python python-3.x multiple-inheritance metaclass built-in

我正在使用Python3.3并注意到以下内容:元类与用户定义的类和多重继承完美配合,但是当一个类继承自内置类型(例如list,tuple,complex ...)时意外地改变了。

首先,一个行为正确的例子:

from abc import ABCMeta, abstractmethod

class A(metaclass=ABCMeta):    
    @abstractmethod
    def say_hello(self):
        print("hello")

class B:
    pass

class C(A, B):
    pass

由于抽象方法say_hello尚未被覆盖,因此在实例化C类时这是正确的结果:

>>> c = C()
Traceback (most recent call last):
  File "<pyshell#42>", line 1, in <module>
    c=C()
TypeError: Can't instantiate abstract class C with abstract methods say_hello

我也用B metaclass尝试了这个,它运行正常。

现在是奇怪的部分。让我们用内置的(在这个例子中list)替换B:

from abc import ABCMeta, abstractmethod

class A(metaclass=ABCMeta):    
    @abstractmethod
    def say_hello(self):
        print("hello")

class C(A, list):
    pass

实例化工作,这不是人们应该期待的:

>>> c = C()
>>>

更糟糕的是,抽象方法可以在没有任何super()的情况下调用:

>>> c.say_hello()
hello

我做错了什么?如果这是一个记录在案的行为,我会很感激,如果有人引用它。

修改 我只是添加评论,因为后果比我预期的更糟:

>>> import numbers
>>> b = 2
>>> isinstance(b, numbers.Integral)
True
>>> isinstance(b, int)
True
>>> b.real
2
>>> class A(numbers.Integral, int):
    pass

>>> a = A()
>>> isinstance(a, int)
True
>>> isinstance(a, numbers.Integral)
True
>>> a.real
Traceback (most recent call last):
  File "<pyshell#114>", line 1, in <module>
    a.real
  File "C:\Python33\lib\numbers.py", line 258, in real
    return +self
  File "C:\Python33\lib\numbers.py", line 89, in __pos__
    raise NotImplementedError
NotImplementedError

0 个答案:

没有答案