列表元素的获取可以使用索引或者切片,这个时候调用的是__getitem__方法
a[i] # 这是一个简单的数字索引,使用即元素“位置”获取元素值
a[i:j];a[i:j:k] # 这是切片操作,i为起始位置,j为结束位置,k为步进值
当使用赋值表达式对元素进行赋值时,调用的时__setitem__方法
a[0]=10
#也可以使用这样的方法替换多个元素
a[0:2]=[11,12]
当使用del语句删除一个值时,调用的是__delitem__方法
del a[0]
del a[0,2]
当使用类似于a[:],a[1:2],a[1,10,2]这样的操作时,实际上是在写slice表达式。slice表达式必须要有三个参数,即起始,结束和步进。之所以我们可以少写参数,是因为内部使用了 indices 这个方法对参数进行了补全。
class Explore(list):
def __getitem__(self, item):
print(item,item.indices(len(self)))
return super().__getitem__(item)
>> a = Explore('1234')
>> a[:]
>> slice(None, None, None) (0, 4, 1) # 虽然我们传入的表达式仅为一个:,但是indices进行了补全
['1', '2', '3', '4']
当我们要使用继承的方式实现自己的list,并且对其中的方法和操作进行自己的一些定义,那么一定不要忘记slice。下面是一个支持平均数和标准差方法的list。
class StatsList(list):
def __init__(self, *args, **kwargs):
self.sum0 = 0 # 列表中元素的个数,len(self)
self.sum1 = 0 # 列表中所有元素的和, sum(self)
self.sum2 = 0 # 列表中所有元素的平方和, sum(x**2 for x in self)
super().__init__(*args, **kwargs)
for x in self:
self._new(x)
# 当添入元素时调用
def _new(self, value):
self.sum0 += 1
self.sum1 += value
self.sum2 += value * value
# 当移除元素时调用
def _rmv(self, value):
self.sum0 -= 1
self.sum1 -= value
self.sum2 -= value * value
def insert(self, index, value):
super().insert(index, value)
self._new(value)
def pop(self, index=-1):
value = super().pop(index)
self._rmv(value)
def __setitem__(self, key, value):
# 如果key是slice实例,那么在进行切片赋值
if isinstance(key, slice):
start, stop, step = key.indices(self.sum0)
for i in range(start, stop, step):
self._rmv(self[i])
super().__setitem__(key, value)
# 这里value不存在不可迭代的情况,因为 slice 操作参数必须为可迭代对象
for x in value:
self._new(x)
else:
self._rmv(self[key])
self._new(value)
super().__setitem__(key, value)
def __delitem__(self, key):
if isinstance(key, slice):
start, stop, step = key.indices(self.sum0)
for i in range(start, stop, step):
self._rmv(self[i])
super().__delitem__(key)
else:
self._rmv(self[key])
super().__delitem__(key)
"""
其他影响计算的函数有: extend, __iadd__, remove, append,
"""
# 平均数
@property
def mean(self):
return self.sum1 / self.sum0
# 标准差
@property
def stdev(self):
return math.sqrt(self.sum0 * self.sum2 - self.sum1 ** 2) / self.sum0