gpt4 book ai didi

python-3.x - __ipow__ 在左侧对象返回 NotImplemented 时引发 TypeError

转载 作者:行者123 更新时间:2023-12-01 12:05:19 26 4
gpt4 key购买 nike

如果我有两个对象 AB,我可以为 A 返回 NotImplemented >__iadd__ 方法,并让 B 使用它的 __radd__ 方法修改 A

>>> class A():
... def __init__(self, val):
... self.val = val
... def __iadd__(self, other):
... return NotImplemented
... def __ipow__(self, other):
... return NotImplemented
...
>>> class B():
... def __init__(self, val):
... self.val = val
... def __radd__(self, other):
... return A(other.val + self.val)
... def __rpow__(self, other):
... return A(other.val ** self.val)
...
>>> a = A(2)
>>> b = B(2)
>>> a += b
>>> a.val
4

这似乎适用于所有 inplace 运算符,但 __ipow__ 除外,其中引发了 TypeError

>>> a **= b
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for ** or pow(): 'A' and 'B'

为什么这里的行为不同?失败是因为 pow() requires numeric data ?最好的解决方法是什么?

最佳答案

Python 3.10+

此错误已在 Python 3.10 中修复

Due to a bug in the dispatching mechanism for **=,a class that defines __ipow__() but returns NotImplementedwould fail to fall back to x.__pow__(y) and y.__rpow__(x).This bug is fixed in Python 3.10.

该代码段现在按预期工作:

>>> a = A(2)
>>> b = B(2)
>>> a **= b
>>> a.val
4

这看起来像是一个错误,因为二进制和三元运算的代码之间存在不一致(**= 由于与 3 参数 共享代码而由三元运算逻辑处理战俘)。二进制就地操作经过 binary_iop1 ,如果就地处理程序返回 NotImplemented,它具有回退到非就地例程的代码:

static PyObject *
binary_iop1(PyObject *v, PyObject *w, const int iop_slot, const int op_slot)
{
PyNumberMethods *mv = v->ob_type->tp_as_number;
if (mv != NULL) {
binaryfunc slot = NB_BINOP(mv, iop_slot);
if (slot) {
PyObject *x = (slot)(v, w);
if (x != Py_NotImplemented) {
return x;
}
Py_DECREF(x);
}
}
return binary_op1(v, w, op_slot);
}

但由于 3 参数 pow 所需的代码差异,**= 无法通过该代码路径,因此它具有 its own ad-hoc handling :

PyObject *
PyNumber_InPlacePower(PyObject *v, PyObject *w, PyObject *z)
{
if (v->ob_type->tp_as_number &&
v->ob_type->tp_as_number->nb_inplace_power != NULL) {
return ternary_op(v, w, z, NB_SLOT(nb_inplace_power), "**=");
}
else {
return ternary_op(v, w, z, NB_SLOT(nb_power), "**=");
}
}

这种临时处理提交到就地或非就地端,如果就地处理程序无法处理它,则不会回退。

关于python-3.x - __ipow__ 在左侧对象返回 NotImplemented 时引发 TypeError,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58141475/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com