列表元素的獲取可以使用索引或者切片,這個時候調用的是__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