When implementing the __getitem__
method in a custom class I expect the second argument to always be a slice obj.
However, when one execute obj[i]
where i
is an integer, obj.__getitem__(self,value)
receives an int
instead of a slice.
This can be tested doing
class MyClass:
def __getitem__(self, sliceobj):
print(type(sliceobj))
a = MyClass()
a[1:5]
a[2:]
a[::2]
a[0]
>> <class 'slice'>
>> <class 'slice'>
>> <class 'slice'>
>> <class 'int'>
This is causing me issues as my class has an internal list (defined in __init__
) and I want to use the slice to iterate over it. The problem is that the output of list[slice]
is not an iterable when slice
is an int
.
In other words:
class MyClass2:
def __getitem__(self, sliceobj):
a_list = [1,2,3,4]
print(sliceobj)
for val in a_list[sliceobj]:
# do stuff
pass
print('it worked')
a = MyClass2()
a[1:3]
a[2:]
a[::2]
a[0]
works for the first 3 calls, but it doesn't for the last, as a_list[0]
is not iterable.
Shouldn't a[0]
be translated in a.__getitem__(slice(0,1))
(that would work) ?
As per the docs:
For sequence types, the accepted keys should be integers and slice objects
You can check if the key is a slice or not and create one:
class MyClass2:
def __getitem__(self, key):
a_list = [1,2,3,4]
keys_to_iterate = key if isinstance(key, slice) else slice(key, key+1)
print(key)
for val in a_list[keys_to_iterate]:
# do stuff
pass
print('it worked')
Running example: https://repl.it/repls/SmallDarkblueWifi