gpt4 book ai didi

python - 实现数字方法总是返回 NotImplemented

转载 作者:太空宇宙 更新时间:2023-11-03 11:08:40 25 4
gpt4 key购买 nike

我正在编写一个新的扩展类型,但我在设置数字运算(例如加法/减法/乘法)时遇到了问题。我已经设法设置了一些就地操作,而没有调用正常操作。

例如,我有这个功能:

static PyObject *
MyType_Mul(PyObject *v, PyObject *w)
{
PyErr_SetString(PyExc_ValueError, "testing");
return NULL;
}

然后我将其设置为这样的数字方法:

static PyNumberMethods my_type_as_number = {
0, /* nb_add */
0, /* nb_sub */
(binaryfunc)MyType_Mul, /* nb_mul */
...
0, /* nb_in_place_add */
0, /* nb_in_place_sub */
(binaryfunc)MyType_Mul, /* nb_in_place_mul */
...
};

现在,当我尝试使用我的类型时,我得到了这种行为:

>>> from mytype import MyType
>>> a = MyType()
>>> a * 2
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for *: 'mytype.MyType' and 'int'
>>> 2 * a
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for *: 'int' and 'mytype.MyType'

但是如果我使用就地运算符:

>>> a *= 2
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: testing

如果我在对象上使用 dir(),我可以看到 __mul____rmul__ 方法(这意味着 python 可以看到它们),但似乎他们根本没有被召唤。使用 a.__mul__(2) 返回 NotImplemented

还有:

>>> a.__mul__
<method-wrapper '__mul__' of mytype.MyType object at 0x7fc2ecc50468>
>>> a.__imul__
<method-wrapper '__imul__' of mytype.MyType object at 0x7fc2ecc50468>

所以,如您所见,它们完全是同一回事。

这是怎么回事?为什么同样的功能适用于就地运算符而不适用于“普通”运算符?我也想过我可能使用了错误的插槽,但我仔细检查它是正确的,并且将它设置为 nb_addnb_sub 等也不起作用。

最佳答案

多亏了 nneonneo 的评论,我明白了哪里出了问题。基本上我忘了设置 Py_TPFLAGS_CHECKTYPES旗帜。

在我给出的描述中有一些关于这种缺失的线索:

  1. 方法是同一个对象,但就地操作的行为不同
  2. 在评论中我还说过,例如,执行 a*a 会产生正确的结果,而执行 a*different-type 则不会。<

这显然意味着解释器在执行非就地操作时正在检查参数的类型,如果类型是 MyType 则调用我的函数,否则返回 NotImplemented.

在文档中稍微搜索一下,很容易看出这是数字方法的默认行为。

如果参数类型不是同一个类,则假定操作未实现。

要允许不同类型一起“操作”,您必须在 MyType 中设置 Py_TPFLAGS_CHECKTYPES 标志:

static PyTypeObject MyType = {
PyObject_HEAD_INIT(&PyType_Type)
0, /*ob_size*/
"mytype.MyType", /*tp_name*/
sizeof(MyTypeObject), /*tp_basicsize*/
0, /*tp_itemsize*/
...
0, /*tp_repr*/
&mytype_as_number, /*tp_as_number*/
0, /*tp_as_sequence*/
...
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES,/*tp_flags*/
...
};

设置此标志后,解释器将不会检查类型,因此您必须手动处理它们。

相反,就地运算符总是允许不同的类型。为什么会这样,我不知道。

关于python - 实现数字方法总是返回 NotImplemented,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12447462/

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