【问题标题】:Why is __getitem__ called in Python 3.5 but not in Python 2.7?为什么在 Python 3.5 中调用了 __getitem__ 而在 Python 2.7 中没有?
【发布时间】:2017-06-22 21:37:50
【问题描述】:

我有一个提供__getitem__ dunder 方法的字节子类。 __getitem__ 方法在 Python 3.5 中总是被调用,但在 Python 2.7 中只对非切片键调用。 (相反,父级的__getitem__ 似乎已应用于实例。)为什么会这样,是否有解决方法?

代码

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 输出

类定义的__getitem__ 总是被调用。

(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 输出

类定义的__getitem__ 仅对非切片键调用。

(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)

【问题讨论】:

  • 噢!更奇怪的是:在 Python 2.7 和 3.5 上使用显式切片(例如 b[slice(0,1,None)]有效调用 __getitem__。看来,在 Python 2.7 中,当 b 是内置类型的子类时,b[s:e]b[slice(s,e)] 的写法相同。

标签: python python-2.7 python-3.x python-3.5 python-internals


【解决方案1】:

Python 2 有 __getslice__,如果存在,它优先于 __getitem__ 进行无级切片。这在 Python 3 中没有了。

【讨论】:

    猜你喜欢
    • 2017-01-18
    • 1970-01-01
    • 2017-01-08
    • 1970-01-01
    • 2012-04-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多