[Tutor] Question on implmenting __getitem__ on custom classes
Steven D'Aprano
steve at pearwood.info
Tue Apr 23 06:10:26 EDT 2019
On Tue, Apr 23, 2019 at 11:46:58AM +0530, Arup Rakshit wrote:
> Hi,
>
> I wrote below 2 classes to explore how __getitem__(self,k) works in
> conjuection with list subscriptions. Both code works. Now my questions
> which way the community encourages more in Python: if isinstance(key,
> slice): or if type(key) == slice: ?
In general, we should normally use `isinstance`, because it works with
subclasses.
But `slice` can't be subclassed:
py> class S(slice):
... pass
...
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: type 'slice' is not an acceptable base type
so there is no advantage to using `isinstance`. (There is no
disadvantage either.)
I would use `type(key) is slice` to guarantee[1] that the key is
certainly a slice.
Why use `is` instead of `==`?
The `is` operator will be a tiny bit faster than `==`, but more
importantly, you could have a class designed to pretend to be a slice.
It isn't easy to do (you would have to write a metaclass, which makes it
an advanced technique) but by using `is` we can eliminate even that slim
chance.
> How should I implement this if I
> follow duck typing, because none of the code currently I wrote using
> duck typing techiniqe IMO.
Why bother? Duck-typing is good for *data* values, but a slice is not a
data value, it is a way of specifying a range of indexes.
> class MyCustomList:
> def __init__(self, list = []):
> self.list = list
Watch out here, you have a mutable default value, that probably doesn't
work the way you expect. The default value is created ONCE, and then
shared, so if you do this:
a = MyCustomList() # Use the default list.
b = MyCustomList() # Shares the same default list!
a.append(1)
print(b.list)
# prints [1]
You probably want:
def __init__(self, list=None):
if list is None:
list = []
self.list = list
> def __getitem__(self, key):
> if isinstance(key, slice):
> return self.list[key]
> else:
> return self.list[key]
The "isinstance" check is useless, because you do precisely the same
thing in both branches.
def __getitem__(self, key):
return self.list[key]
will do exactly the same, and more efficiently.
[1] Not actually a guarantee.
--
Steven
More information about the Tutor
mailing list