Reece
Reece

Reputation: 8088

Why is __getitem__ called in Python 3.5 but not in Python 2.7?

I have a subclass of bytes that provides a __getitem__ dunder method. The __getitem__ method is always called in Python 3.5, but is called only for non-slice keys in Python 2.7. (Instead, it appears that parent's __getitem__ is applied to the instance.) Why is this and is there a workaround?

Code

class A(object):
    def __getitem__(self, key):
        print("in A.__getitem__ with key " + str(key))
        return []

class B(bytes):
    def __getitem__(self, key):
        print("in B.__getitem__ with key " + str(key))
        return []

if __name__ == "__main__":
    import sys
    print(sys.version)

    a = A()
    b = B()

    print("[0]")
    a[0]
    b[0]

    print("[0:1]")
    a[0:1]
    b[0:1]

    print("[:1]")
    a[:1]
    b[:1]

Python 3.5 Output

The class-defined __getitem__ is always called.

(venv) snafu$ python ./x.py
3.5.2 (default, Nov 17 2016, 17:05:23) 
[GCC 5.4.0 20160609]
[0]
in A.__getitem__ with key 0
in B.__getitem__ with key 0
[0:1]
in A.__getitem__ with key slice(0, 1, None)
in B.__getitem__ with key slice(0, 1, None)
[:1]
in A.__getitem__ with key slice(None, 1, None)
in B.__getitem__ with key slice(None, 1, None)

Python 2.7 Output

The class-defined __getitem__ is called only for non-slice keys.

(venv2.7) snafu$ python x.py
2.7.12 (default, Nov 19 2016, 06:48:10) 
[GCC 5.4.0 20160609]
[0]
in A.__getitem__ with key 0
in B.__getitem__ with key 0
[0:1]
in A.__getitem__ with key slice(0, 1, None)
[:1]
in A.__getitem__ with key slice(None, 1, None)

Upvotes: 1

Views: 567

Answers (1)

user2357112
user2357112

Reputation: 281151

Python 2 has __getslice__, which takes priority over __getitem__ for stepless slicing if present. That's gone in Python 3.

Upvotes: 6

Related Questions