Since some days ago I was unaware of the __index__()
method until reading this question. After that, I have been reading about it in the documentation, PEP and in other SO questions.
I understood that whenever the []
operator was used in objects that could be sliced (in my case I'm interested in lists, numpy arrays and pandas), the value either for slicing or for indexing was obtained so that lst[key]=lst[key.__index__()]
was fulfilled.
However, as in one of the questions, the result depended on whether PyPy or CPython was used, so I decided to check when was slicing actually done with __index__
and when it was not. I have done the following (in CPython 2.7.14):
lst = range(10)
array = np.arange(10)
series = pd.Series(lst)
And defined the following classes:
class MyIndex:
def __index__(self):
return 2
class MyInt(int):
def __index__(self):
return 3
class MyStr(str):
def __index__(self):
return 4
Then I tried to acces the defined objects with this used defined objects, obtaining the following:
Note: I am not posting the complete error message for readability purposes.
For MyIndex
class, expected output 2:
print lst[MyIndex()]
print array[MyIndex()]
print series[MyIndex()]
# Output:
2
2
AttributeError: MyIndex instance has no attribute '__trunc__'
For MyInt
class, expected output 3:
# Case 1
print lst[MyInt()]
print array[MyInt()]
print series[MyInt()]
# Output
0
0
0
# Case 2
print lst[MyInt(2)]
print array[MyInt(2)]
print series[MyInt(2)]
# Output
2
2
2
For MyStr
class, expected output 4:
# Case 1
print lst[MyStr()]
print array[MyStr()]
print series[MyStr()]
# Output
4
4
KeyError: ''
# Case 2
print lst[MyStr('a')]
print array[MyStr('a')]
print series[MyStr('a')]
# Output
4
IndexError: only integers, slices (`:`), ellipsis (`...`), numpy.newaxis (`None`) and integer or boolean arrays are valid indices
KeyError: 'a'
I'm really puzzled by this, mainly by the following points:
- With lists the
__index__
method is used but not forint
and its childrens. - Numpy uses
__index__
like lists, but in the last caseMyStr('a')
raises an error. Am I missing something or in this case__index__
is only used whenMyStr
is an empty string? - Pandas slicing is a whole world and even accepts slicing for ordered string index, so it is a relieve that
__index__
is not used. Thus, my only question about pandas is if the output of a code could be different depending on the python implementation.
My question is basically the one in the title:
When is
__index__
called for lists and numpy arrays? Why are there some exceptions?
Having said that, I will be happy to recieve any extra information I may have missed about this method.