我下面有一个简单的类(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.index
与MyClass
实例一起使用时,我得到了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/