Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/69.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 注册abc实现而不将其添加到mro_Python_Python 3.x - Fatal编程技术网

Python 注册abc实现而不将其添加到mro

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

我试图理解abc.ABCMeta的方法寄存器的有用性。 据我所知,阅读后:

以下代码:

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
是错误的


我希望这至少能让事情更清楚一点。

谢谢,现在我甚至可以看到我的问题写得很糟糕:)