我做了一个如下的课程:
class MyList(list):
def __init__(self, lst):
self.list = lst
我希望在 MyList 中覆盖切片功能
我做了一个如下的课程:
class MyList(list):
def __init__(self, lst):
self.list = lst
我希望在 MyList 中覆盖切片功能
您需要提供 custom和__getitem__()
hooks 。__setitem__
__delitem__
这些在对列表进行切片时传递一个切片对象;这些具有start
,stop
和step
属性。但是,这些值可以是None
, 以表示默认值。考虑到当您使用负步幅时默认值实际上会发生变化!
但是,它们也有一个slice.indices()
方法,当给定一个长度时,它会产生一个(start, stop, step)
适合range()
对象的值的元组。此方法处理诸如以负步幅进行切片且没有开始或停止索引等令人讨厌的细节:
def __getitem__(self, key):
if isinstance(key, slice):
indices = range(*key.indices(len(self.list)))
return [self.list[i] for i in indices]
return self.list[key]
或者,对于您的情况:
def __getitem__(self, key):
return self.list[key]
因为 alist
可以直接取slice
对象。
在 Python 2 中,list.__getslice__
如果实现了没有跨步的切片(因此只有开始和停止索引),则调用它,并且内置list
类型实现了它,因此您也必须覆盖它;对您的方法的简单委托__getitem__
应该可以:
def __getslice__(self, i, j):
return self.__getitem__(slice(i, j))
class MyList(list):
def __init__(self, lst):
self.list = lst
没有多大意义......self
是列表对象本身,并且此时它已经创建,也许您想要覆盖__new__
,但是您可能不需要触摸它。无论如何,您想像这样覆盖__getitem__
:
def __getitem__(self, val):
if isinstance( val, slice):
# do stuff here
正如@Martijn Pieters和@jamylak所说,您需要实现该__getitem__
方法。
一般来说,如果一个人想要覆盖它的超类的切片功能,并继续使用已经使用超类的超类方法__getitem__
,只需将其拆分为案例,并从两个世界中受益。
例如:
import pandas as pd
class SubFrame(pd.DataFrame):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
def __getitem__(self, item):
if isinstance(item, slice):
# your implementation
print("'My slicing'")
return SubFrame(super().__getitem__(item))
else:
return super().__getitem__(item)
现在你可以这样做:
>>> sf = SubFrame({'A': (10,20,30,40,50)})
>>> sf[1:-2]
'My slicing'
A
1 20
2 30
>>> type(sf[1:-2])
<class '__main__.SubFrame'>
并且[]
仍然会打电话给超级的__getitem__
>>> sf['A'] # super's __getitem__
0 10
1 20
2 30
3 40
4 50
Name: A, dtype: int64
>>> type(sf['A'])
<class 'pandas.core.series.Series'>