我正在使用Python 2.7,并且试图从继承AppData/Local/Microsoft/TypeScript/2.9/node_modules/@types
的类中重载__getitem__
和__setitem__
。
让我说我上了这个课:
list
应使用方括号 class A(list):
def __getitem__(self, key):
print "GET!"
def __setitem__(self, key, value):
print "SET!"
或__getitem__
。通常情况就是这样,但是当我使用__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__
答案 0 :(得分:8)
那是因为在Python 2中 [1] [:]
以及带有 start 和/或 end 的一维切片(但如果指定了 step ,则不会),例如[1:]
,[:3]
或[1:3]
,如果它们是__getslice__
和__setslice__
已实施。如果未实现,它们还将转到__getitem__
和__setitem__
)。引用文档:
请注意,只有在使用具有单个冒号的单个切片并且切片方法可用时,才调用这些方法[
__*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)]
的原因,尽管它似乎等效于[:]
却直接进入了{{1 }},而不是__*item__
。
[1] 在Python 3中,__*slice__
方法被删除,因此__*slice__
索引将转到[whatever]
方法。