Effective Python 讀書筆記 - 第2章 列表與字典

博客地址:https://www.hz-bin.cn/Effective_Python_2

第11條 學(xué)會對序列做切片

  • 最基本的寫法是用somelist[start:end]這一形式來切割,也就是從start開始一直取到end這個位置,但不包含end本身的元素。切割出來的列表是一份全新的列表
a       = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
a[:]    # ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
a[:5]   # ['a', 'b', 'c', 'd', 'e']
a[:-1]  # ['a', 'b', 'c', 'd', 'e', 'f', 'g']
a[4:]   #                     ['e', 'f', 'g', 'h']
a[-3:]  #                          ['f', 'g', 'h']
a[2:5]  #           ['c', 'd', 'e']
a[2:-1] #           ['c', 'd', 'e', 'f', 'g']
a[-3:-1]#                          ['f', 'g']
  • 切片可以出現(xiàn)在賦值符號的左側(cè),表示用右側(cè)那些元素把原列表中位于這個范圍之內(nèi)的元素?fù)Q掉,不要求兩邊元素個數(shù)相同
a = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
a[2:7] = [99, 22, 14]
# a 變成:['a', 'b', 99, 22, 14, 'h']
a[2:3] = [47, 11]
# a 變成:['a', 'b', 47, 11, 22, 14, 'h']
a = [1, 2, 3]
b = a
print(a, b)
# ([1, 2, 3], [1, 2, 3])

a[:] = [101, 102, 103]
print(a, b)
# ([101, 102, 103], [101, 102, 103])

第12條 不要在切片里同時指定起止下標(biāo)與步進(jìn)

  • Python還有一種特殊的步進(jìn)切片形式,也就是 somelist[start:end:stride]。這種形式會在每n個元素里面選取一個,這樣很容易就能把奇數(shù)位置上的元素與偶數(shù)位置上的元素分別通過 x[::2]x[1::2] 選取出來
  • 同時指定切片的起止下標(biāo)與步進(jìn)值理解起來會很困難。
  • 如果要指定步進(jìn)值,那就省略起止下標(biāo),而且最好采用正數(shù)作為步進(jìn)值,盡量別用負(fù)數(shù)。
  • 不要把起始位置、終止位置與步進(jìn)值全都寫在同一個切片操作里。如果必須同時使用這三項指標(biāo),那就分兩次來做(其中一次隔位選取,另一次做切割),也可以改用itertools內(nèi)置模塊里的islice方法。

第13條 通過帶星號的unpacking操作來捕獲多個元素,不要用切片

car_ages = [0, 9, 4, 8, 7, 20, 19, 1, 6, 15]
car_ages_desceding = sorted(car_ages, reverse=True)
oldest, second_oldest, *others = car_ages_descending
oldest, *others, yongest = car_ages_descending
  • 使用這種寫法時,至少要有一個普通的接收變量與它搭配,否則就會出現(xiàn)SyntaxError。

第14條 用sort方法的key參數(shù)來表示復(fù)雜的排序邏輯

class Tool:
    def __init__(self, name, weight):
        self.name = name
        self.weight = weight

    def __repr__(self):
        return f'Tool({self.name!r}, self.weight)'

tools = [
    Tool('level', 3.5),
    Tool('hammer', 0.25),
    Tool('screwdriver', 0.5),
    Tool('chisel', 0.25),
]

tools.sort(key=lambda x: x.name)
# 先按weight排序,再按name排序。reverse=True表示逆序
tools.sort(key=lambda x: (x.weight, x.name), reverse=True)
# weight逆序,name正序
tools.sort(key=lambda x: (-x.weight, x.name))

第15條 不要過分依賴給字典添加條目時所用的順序

  • 在Python 3.5與之前的版本中,dict所提供的許多方法(包括keys、values、items與popitem等)都不保證固定的順序。
  • 從Python 3.6開始,字典會保留這些鍵值對在添加時所用的順序,而且Python3.7版的語言規(guī)范正式確立了這條規(guī)則。

第16條 用get處理鍵不在字典中的情況,不要使用in與KeyError

  • 有四種辦法可以處理鍵不在字典中的情況:in表達(dá)式、KeyError異常、get方法與setdefault方法。
  • 如果跟鍵相關(guān)聯(lián)的值是像計數(shù)器這樣的基本類型,那么get方法就是最好的方案;如果是那種構(gòu)造起來開銷比較大,或是容易出異常的類型,那么可以把這個方法與賦值表達(dá)式結(jié)合起來使用。
  • 即使看上去最應(yīng)該使用setdefault方案,也不一定要真的使用setdefault方案,而是可以考慮用defaultdict取代普通的dict。

第17條 用defaultdict處理內(nèi)部狀態(tài)中缺失的元素,而不要用setdefault

  • 如果你管理的字典可能需要添加任意的鍵,那么應(yīng)該考慮能否用內(nèi)置的collections模塊中的defaultdict實(shí)例來解決問題。
  • 如果這種鍵名比較隨意的字典是別人傳給你的,你無法把它創(chuàng)建成defaultdict,那么應(yīng)該考慮通過get方法訪問其中的鍵值。然而,在個別情況下,也可以考慮改用setdefault方法,因為那樣寫更短。
from collections import defaultdict

class Visits:
    def __init__(self):
        self.data = defaultdict(set)

    def add(self, country, city):
        self.data[country].add(city)

第18條 學(xué)會利用missing構(gòu)造依賴鍵的默認(rèn)值

class Pictures(dict):
    def __missing__(self, key):
        value = open_picture(key)
        self[key] = value
        return value

pictures = Pictures()
handle = pictures[path]
handle.seek(0)
image_data = handle.read()
  • 如果創(chuàng)建默認(rèn)值需要較大的開銷,或者可能拋出異常,那就不適合用dict類型的setdefault方法實(shí)現(xiàn)。
  • 傳給defaultdict的函數(shù)必須是不需要參數(shù)的函數(shù),所以無法創(chuàng)建出需要依賴鍵名的默認(rèn)值。
  • 如果要構(gòu)造的默認(rèn)值必須根據(jù)鍵名來確定,那么可以定義自己的dict子類并實(shí)現(xiàn)missing方法。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容