提问人:Aniol 提问时间:7/12/2018 最后编辑:smciAniol 更新时间:7/2/2019 访问量:1087
为什么当我使用 [:] 时,我的子类的 __getitem__ 和 __setitem__ 没有被调用?
Why are my subclass's __getitem__ and __setitem__ not called when I use [:]?
问:
我正在研究 Python 2.7,我正在尝试重载并从继承 .__getitem__
__setitem__
list
假设我有这个类: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 的 1-d 切片(但在指定步骤时不是这样),例如 、 ,或者如果它们被实现,则通过 __getslice__
和 __setslice__
。如果它们没有实现,它们也将转到 和 )。引用文档:[:]
[1:]
[:3]
[1:3]
__getitem__
__setitem__
请注意,仅当使用具有单个冒号的单个切片并且切片方法可用时,才会调用这些方法 []。对于涉及扩展切片表示法的切片操作,或者在没有切片方法的情况下,使用 slice 对象作为参数调用 。
__*slice__
__getitem__()
__setitem__()
__delitem__()
在你的情况下,你继承了它们(实现它们),所以它绕过了你的和在简单的切片情况下。list
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__
评论
[::]
slice(None)
tuple
slice
a[slice(None)]
[::]
__*slice__
下一个:切片跨越字符串边界?
评论