gpt4 book ai didi

python - 当我使用 [ :]? 时,为什么我的子类的 __getitem__ 和 __setitem__ 没有被调用

转载 作者:太空狗 更新时间:2023-10-29 21:38:35 26 4
gpt4 key购买 nike

我正在使用 Python 2.7,我正在尝试从继承 list 的类中重载 __getitem____setitem__

假设我有这个类 A:

 class A(list):
def __getitem__(self, key):
print "GET!"

def __setitem__(self, key, value):
print "SET!"

使用方括号,应该调用 A.__getitem__A.__setitem__。通常是这样,但是当我使用 [:] 时,会调用父实现。为什么?为什么 [::] 有效?

a = A([1])
a[1] # prints GET!
a["1"] # prints GET!
a[::] # prints GET!
a[slice(None)] # prints GET!
a[:] # returns the list [1]

__setitem__ 相同:

a[1] = 2 # prints SET!
a[::] = 2 # prints SET!
a[slice(None)] = 2 # prints SET!
a[:] = [2] # changes the list

最佳答案

那是因为在 Python 2 [1] [:] 以及带有 start 和/或 的一维切片end(但不是在指定 step 时),如 [1:][:3][ 1:3] 遍历 __getslice____setslice__如果它们得到实现。如果未实现,它们也将转到 __getitem____setitem__)。引用文档:

Notice that these methods [__*slice__] are only invoked when a single slice with a single colon is used, and the slice method is available. For slice operations involving extended slice notation, or in absence of the slice methods, __getitem__(), __setitem__() or __delitem__() is called with a slice object as argument.

在你的情况下,你从listinherit它们(list实现它们)所以它绕过你的__getitem____setitem__ 在简单的切片情况下。

例如,您可以覆盖 __*slice__ 方法来验证 [:] 调用是否真的到达那里:

class A(list):
def __getitem__(self, key):
print "GET!"

def __setitem__(self, key, value):
print "SET!"

def __getslice__(self, i, j):
print "GETSLICE!"

def __setslice__(self, i, j, seq):
print "SETSLICE!"

然而,这些仅在仅传入一个切片且仅当传递的切片没有步骤时才会调用。所以 [::] 不会去那里,因为它有一个步骤(即使它是隐式的)。但是 [:,:] 也不会进入这些,因为它被翻译成 tuple(slice(None), slice(None)) 这不是一个简单的切片但是切片的元组。如果您自己传入一个 slice 实例,它也不会进入这些 __*slice__ 方法,这就是为什么 [slice(None)]尽管看似等同于 [:] 直接进入 __*item__ 而不是 __*slice__


[1] 在 Python 3 中,__*slice__ 方法被移除,因此 [whatever] 索引将转到 __*item__ 方法。

关于python - 当我使用 [ :]? 时,为什么我的子类的 __getitem__ 和 __setitem__ 没有被调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51301206/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com