Python 注册abc实现而不将其添加到mro
我试图理解abc.ABCMeta的方法寄存器的有用性。 据我所知,阅读后: 以下代码:Python 注册abc实现而不将其添加到mro,python,python-3.x,Python,Python 3.x,我试图理解abc.ABCMeta的方法寄存器的有用性。 据我所知,阅读后: 以下代码: class MyFoo(Complex): ... MyFoo.register(Real) 将创建实现复杂抽象类的类MyFoo。 在用Real注册MyFoo之后,isinstance和issubclass将返回,就好像MyFoo是从Real派生的一样。 我不明白的是,为什么真的没有被添加到mro中 我之所以这么问,是因为以下代码不会像我预期的那样运行: def trunc(inst): i
class MyFoo(Complex): ...
MyFoo.register(Real)
将创建实现复杂抽象类的类MyFoo。
在用Real注册MyFoo之后,isinstance和issubclass将返回,就好像MyFoo是从Real派生的一样。
我不明白的是,为什么真的没有被添加到mro中
我之所以这么问,是因为以下代码不会像我预期的那样运行:
def trunc(inst):
if isinstance(inst, Real):
return inst.__trunc__() #this should generate error since Complex doesn't have the __trunc__ attr
else:
return NotImplemented
trunc(MyFoo())
当isinstance返回true时,底层对象是否应该具有它所检查的类的所有特征
请注意,如果不明显,我对该语言相当陌生,因此请耐心等待。使用isinstance
检查对象的属性
的思想是提供一种方法来覆盖无法控制的类型的isinstance
行为
例如,您可能希望使用isinstance
检查对象是否支持添加(即允许对满足检查的a
和b
执行a+b
)
为此,您可以实现一个基类和一些子类:
class TypeWithAddition:
def __add__(self, other):
raise NotImplementedError("Override __add__ in the subclass")
class MyClass(TypeWithAddition):
def __init__(self, value):
self.value = value
def __add__(self, other):
return MyClass(self.value + other.value)
然后,在尝试对任意两个对象求和之前,可以检查isinstance
。
例如:
a = MyClass(7)
b = MyClass(8)
if isinstance(a, TypeWithAddition) and isinstance(b, TypeWithAddition):
c = a + b
print(c.value)
else:
print('Cannot calculate a+b')
使用ABC
扩展现有类的isinstance
这种方法的问题在于,它不适用于已经存在并支持添加的类型,但这些类型不是从基类继承的:
>>> isinstance(7, TypeWithAddition)
False
这就是ABC开始的地方。可以从ABC
继承基本(“接口”)类,然后向其注册任何现有类
class TypeWithAddition(abc.ABC):
def __add__(self, other):
raise NotImplementedError("Override __add__ in the subclass")
TypeWithAddition.register(int)
现在看来,int
是从TypeWithAddition
继承的:
>>> isinstance(7, TypeWithAddition)
True
但是当然,int
并不是真正继承自TypeWithAddition
!而且实际上没有检查它是否支持您希望从TypeWithAddition
获得的所有功能。在编写TypeWithAddition.register(int)
之前,您(程序员)的工作就是确保它完成了
错误:
您可以很容易地做到这一点,当然,它不会很好地工作:
class Foo:
pass
TypeWithAddition.register(Foo)
现在看来Foo
支持添加,但它不支持:
>>> Foo() + Foo()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'Foo' and 'Foo'
>>Foo()+Foo()
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
TypeError:不支持+:“Foo”和“Foo”的操作数类型
它不起作用,因为首先将Foo
注册为TypeWithAddition
是错误的
我希望这至少能让事情更清楚一点。谢谢,现在我甚至可以看到我的问题写得很糟糕:)