python - 带有自定义类实例的operator.index

标签 python python-3.x

我下面有一个简单的类(class),

class MyClass(int):
    def __index__(self):
        return 1
根据operator.index文档,

operator.index(a)

Return a converted to an integer. Equivalent to a.__index__()


但是,当我将operator.indexMyClass实例一起使用时,我得到了100而不是1(如果我使用1,则得到a.__index__())。这是为什么?。
>>> a = MyClass(100)
>>>
>>> import operator
>>> print(operator.index(a))
100
>>> print(a.__index__())
1

最佳答案

这是因为您的类型是int子类。因为实例已经是整数,所以将不使用__index__。这么多是设计使然,不太可能被认为是CPython中的错误。 PyPy的行为相同。
_operator.c 中:

static PyObject *
_operator_index(PyObject *module, PyObject *a)
/*[clinic end generated code: output=d972b0764ac305fc input=6f54d50ea64a579c]*/
{
    return PyNumber_Index(a);
}
请注意,通常不使用operator.py Python代码,此代码仅是fallback in the case that compiled _operator module is not available。这就解释了为什么结果a.__index__()不同。
abstract.c 中,在相关的PyLong_Check部分之后裁剪:
/* Return an exact Python int from the object item.
   Raise TypeError if the result is not an int
   or if the object cannot be interpreted as an index.
*/
PyObject *
PyNumber_Index(PyObject *item)
{
    PyObject *result = _PyNumber_Index(item);
    if (result != NULL && !PyLong_CheckExact(result)) {
        Py_SETREF(result, _PyLong_Copy((PyLongObject *)result));
    }
    return result;
}

...

/* Return a Python int from the object item.
   Can return an instance of int subclass.
   Raise TypeError if the result is not an int
   or if the object cannot be interpreted as an index.
*/
PyObject *
_PyNumber_Index(PyObject *item)
{
    PyObject *result = NULL;
    if (item == NULL) {
        return null_error();
    }

    if (PyLong_Check(item)) {
        Py_INCREF(item);
        return item;     /* <---- short-circuited here */
    }
    ...
}
operator.index的文档不正确,因此这可能被认为是次要的文档问题:
>>> import operator
>>> operator.index.__doc__
'Same as a.__index__()'
那么,为什么不为整数考虑__index__呢?可能的答案在PEP 357的名为Speed的讨论部分下找到:

Implementation should not slow down Python because integers and long integers used as indexes will complete in the same number of instructions. The only change will be that what used to generate an error will now be acceptable.


我们不想放慢使用整数切片的最常见情况,而每次都必须检查nb_index插槽。

关于python - 带有自定义类实例的operator.index,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65551469/

相关文章:

python - 如何下载适用于 Python 3.5.1 的 Pygame?

Python Key Error 过滤 MySQL

python - 从 Python 2.x 或 3.x 开始?

python-3.x - 如果列表中包含任何项目

java - Intellij 默认 SDK 未使用路径问题

python - 从 csv.reader 打印

python - 如何创建任意长度字符串的numpy数组?

Python 保存到不同的工作簿

python - wxPython:如何一键清除TextCtrl中的默认文本

python - 在非标准路径配置中编译具有静态链接 python 支持的 vim