Written by Python高效編程
應(yīng)用
- 大文本查找單詞并修改
- 重命名圖片或者文件
- 小型數(shù)據(jù)庫(kù)
- 特定目的的 GUI
- 簡(jiǎn)單的小游戲
流程:寫程序/編譯/測(cè)試/重編譯 過程漫長(zhǎng)
shell 適合移動(dòng)代赁、修改文件宪哩,但不適合用戶界面或者游戲
c/c++/Java 耗時(shí)過長(zhǎng),即使是初稿
Python 使用起來更簡(jiǎn)單折联,跨平臺(tái)颓屑,幫助你更快速地完成工作斤寂。
Python 雖然簡(jiǎn)單易用,但也是通用編程語(yǔ)言揪惦。相較于其他腳本語(yǔ)言遍搞,Python 提供了多得多的適合于大型項(xiàng)目的結(jié)構(gòu)與支持。作為高級(jí)語(yǔ)言器腋,Python 相較于 C 語(yǔ)言提供更多的錯(cuò)誤檢查溪猿,并且有高度封裝的數(shù)據(jù)類型钩杰,比如靈活的矩陣和字典。Python 相較于 Awk 甚至是 Perl诊县,事何更加復(fù)雜的領(lǐng)域讲弄,盡管許多方面使用起來差不多方便。
Python 允許你把程序分割成可以重復(fù)使用的模塊依痊,你可以將模塊用在其他 Python 項(xiàng)目中避除。你還可以使用 Python 內(nèi)置的標(biāo)準(zhǔn)模塊,或者作為開始學(xué)習(xí) Python 的范例抗悍。一些模塊提供:文件讀取寫入驹饺,系統(tǒng)調(diào)用,sockets編程,甚至是用戶界面接口工具 TK。
Python 是解釋型語(yǔ)言邑滨,編譯和linking是不必要的匿值,在程序開發(fā)的時(shí)候,可以節(jié)省可觀的時(shí)間读虏。你可以通過交互式終端執(zhí)行 Python 程序,因此很容易就可以實(shí)驗(yàn)語(yǔ)言的特性,寫一些一次性的程序指蚁,或者在自下而上開發(fā)時(shí)測(cè)試函數(shù)。同時(shí)自晰,Python 是容易使用的桌面計(jì)算器凝化。
可擴(kuò)展性強(qiáng)
非正式介紹
數(shù)值類型:浮點(diǎn)型,整型酬荞,復(fù)數(shù)(j or J) , 字符串
各種操作符 :// , / , * 搓劫,** ,%混巧,+/-
先賦值枪向,再使用
整型 + 浮點(diǎn)數(shù) = 浮點(diǎn)數(shù)
交互模式 _ = ans
字符串
- ‘ . . . ’ or “ . . . ” 單引號(hào)或者雙引號(hào)
- \ 可以忽略‘ “ it’s ok!” 或者 ‘ It'ok ’ 或者 ‘ yes “好的呢” ’
- 交互模式,輸出字符以引號(hào)括起咧党,特殊字符仍保留(\n)
- print 沒有引號(hào)秘蛔,沒有特殊字符
- 不想
\
被解釋為特殊字符,使用原生字符串(raw strings)在第一個(gè)引號(hào)前 - 字符串可以跨越多行傍衡。一種方式是使用三個(gè)引號(hào)
‘''...'’'
或者·“""...""”
- 也可以使用
\
注釋 - +連*倍
-
‘Py’
‘thon'
連 - 當(dāng)你想斷開長(zhǎng)字符深员,這個(gè)方法特別又要
- 只有個(gè)部分均為字符串文字(literals),而不是變量或者表達(dá)式
- 連接變量與文字 請(qǐng)使用
+
- 支持 index 0 起始
- 沒有單獨(dú)的字符類型(char)蛙埂,一個(gè)字符就是長(zhǎng)度為1的字符串
- 支持負(fù)數(shù)下標(biāo)倦畅,從右開始 -1
- 切片操作
- 索引獲取單個(gè)字符,切片獲取子字符串
- s = s[:i] + s[i:]
- 省略的第一個(gè)下標(biāo)默認(rèn)為 0
- 省略的第二個(gè)下標(biāo)默認(rèn)為字符串長(zhǎng)度
- 標(biāo)上序號(hào)記憶
P | y | t | h | o | n | |
---|---|---|---|---|---|---|
0 | 1 | 2 | 3 | 4 | 5 | 6 |
-6 | -5 | -4 | -3 | -2 | -1 |
- 左開右閉
- 索引不能超過大小
- 而切片卻可以
- strings 常量不可修改(immutable:numbers,strings,tuples:(1,2))
- word[0] = ‘J’
- len(s) 返回字符串大小
列表
- 復(fù)合數(shù)據(jù)類型
- 寫作方括號(hào)與逗號(hào)的組合
- 支持索引與切片
- [:] 淺拷貝
- 支持+*
- 可修改 cube(立方)
- append 后插
- 賦值 可以改變列表大小箱残,甚至清空
- letters[2:5] = [‘d’,‘e’] or []
- 支持 len
- 嵌入子列表
更加復(fù)雜的任務(wù)
# 斐波那契數(shù)列
a, b = 0,1
while b < 10:
print(b)
a, b = b, a + b
- 多賦值 a,b = b,a simultaneously
- 表達(dá)式順序
- 左右 = 首先執(zhí)行
- while 一直執(zhí)行滔迈,只要判斷條件成立
- 類似 C止吁,任何非零值都是成立的,0 是 False。
- 字符串燎悍、列表敬惦、任何不為空的序列。
- 各種比較符 與 C 類似
- 循環(huán)的主體是要縮進(jìn)的谈山,縮進(jìn)是 Python 組成語(yǔ)句的方式俄删。
- Tab 四個(gè)字符縮進(jìn)
- print 打印多個(gè)參數(shù),浮點(diǎn)數(shù)奏路,字符串
- 字符串無引號(hào)畴椰,以逗號(hào)隔開的元素,打印時(shí)會(huì)用空格隔開
- end 參數(shù)用于分隔每個(gè) print 打印的內(nèi)容 ‘,’ 避免換行
- 優(yōu)先級(jí)
if 語(yǔ)句
- 類似其他語(yǔ)言的條件語(yǔ)句
- if x < 0 :
- elif x == 0:
- else:
- elif 可以有 0 個(gè)鸽粉,或是更多斜脂,else是可選的
- elif 是 else if 的縮寫,避免了不必要的1縮進(jìn)
- 可替代 switch case
for 語(yǔ)句
- 有些不同 相對(duì)于 C 和 Pascal
- C 中既定義了迭代條件和停止條件
- for 迭代 任何序列的元素(列表或者字符串)触机,按照出現(xiàn)順序
- words
- 如果迭代時(shí)你想修改序列值帚戳,推薦先做個(gè)拷貝
- 迭代并不會(huì)拷貝數(shù)值
- 切片隱式拷貝[:] 特別方便
- 不拷貝,會(huì)無限迭代儡首,創(chuàng)建無窮列表
words = ['cat', 'window', 'defenestrate']
for w in words[:]:
if len(w) > 6:
words.insert(0, w)
range() 函數(shù)
- 迭代數(shù)字序列
- range(10) 序列大小為 10
- 合理的索引值為 10
- 不包含結(jié)束點(diǎn)片任,默認(rèn)初始值為 0
- 可以設(shè)置間隔或者步長(zhǎng)(甚至可以是負(fù)數(shù))
- range(-10, -100, -30)
- 為了可以迭代序列的索引,可以同時(shí)使用 range 和 len
- enumerate()
- strange: print(range(10))
- range 似乎是個(gè)列表蔬胯,實(shí)際上不是
它是一個(gè)當(dāng)你迭代它時(shí)对供,返回迭代序列連續(xù)元素的對(duì)象。但是它并不生成列表氛濒,因此節(jié)省了空間产场。這樣的對(duì)象是可迭代的,這種結(jié)構(gòu)的特點(diǎn)是:你可以連續(xù)從中獲取元素泼橘,直到?jīng)]有為止涝动。for 語(yǔ)句是迭代器,函數(shù)list()
也是迭代器炬灭,它可以從可迭代對(duì)象中創(chuàng)建列表
break continue else
- break 跳出最內(nèi)層循環(huán)醋粟,只跳出一層循環(huán)
- else 子句
- 當(dāng) for 循環(huán)結(jié)束,執(zhí)行else 或者 while 判斷條件為 False
- 與 for 一起使用 類似于與 try 一起使用
- try : else 用于沒有異常發(fā)生重归,for : else 用于沒有 break 語(yǔ)句
for n in range(2, 10):
for x in range(2, n):
if n % x == 0:
print(n, 'equals', x, '*', n//x)
break
else:
# loop fell through without finding a factor
print(n, 'is a prime number')
- continue 也是從 C 中借用的語(yǔ)句米愿,繼續(xù)開始下一次的迭代
pass
- pass 語(yǔ)句什么都不做,當(dāng)語(yǔ)法上需要但是不需要執(zhí)行的時(shí)候
- While True : pass
- class MyEmptyClass : pass
- 函數(shù)占位鼻吮,條件主體育苟,允許你考慮更抽象的水平
定義函數(shù)
def fib(n):
a, b = 0, 1
while a < n:
print(a, end=' ')
a, b = b, a+b
print()
- 創(chuàng)建斐波那契函數(shù)到任意邊界
- def 關(guān)鍵字用于定義函數(shù) + 函數(shù)名 + (參數(shù))
- 語(yǔ)句形成了函數(shù)的主體。必須被縮進(jìn)
- 函數(shù)主體的第一條語(yǔ)句可以是字符串
- 字符串是函數(shù)的說明文檔(docstring)
- 養(yǎng)成說明的習(xí)慣
- 函數(shù)的執(zhí)行引進(jìn)了新的符號(hào)表椎木,局部變量
更準(zhǔn)確地說违柏,在函數(shù)中分配的變量博烂,儲(chǔ)存在局部符號(hào)表格中(locak symbol table)
變量引用查找局部變量符號(hào)表格,然后是封閉函數(shù)的局部符號(hào)表格漱竖,接著是全局符號(hào)表格禽篱,最后是內(nèi)置函數(shù)名。因此馍惹,全局變量不能直接在函數(shù)中直接賦值給全局變量(除非使用 global 語(yǔ)句)躺率,盡管我們可以引用全局變量。
函數(shù)的實(shí)參万矾,在被調(diào)用函數(shù)的局部符號(hào)表格中悼吱。因此函數(shù)傳遞參數(shù)的引用,而不是參數(shù)的值良狈。數(shù)值不會(huì)被改變(常量)后添,列表會(huì)被改變。
當(dāng)函數(shù)調(diào)用另一個(gè)函數(shù)们颜,這次調(diào)用會(huì)創(chuàng)建新的局部符號(hào)表格吕朵。
函數(shù)定義在當(dāng)前符號(hào)表格中引進(jìn)了新的函數(shù)名。函數(shù)名的值的類型被解釋器當(dāng)成用戶定義函數(shù)窥突。這個(gè)值可以分配其他名字,我們可以通過其他名字調(diào)用這個(gè)函數(shù)硫嘶,這就是重命名機(jī)制的原理:
fib
f = fib
f(100)
函數(shù)沒有 return 語(yǔ)句也會(huì)返回值阻问,return None
,None 被解釋器抑制了沦疾。如果它是唯一寫入的值称近,對(duì)于交互模式解釋器,使用print
哮塞。
- return 語(yǔ)句從函數(shù)中返回?cái)?shù)值刨秆,return 后面沒有表達(dá)式參數(shù)的話,會(huì)返回 None忆畅。
- ulist.append 被稱為 list 對(duì)象 ulist 的方法衡未。這個(gè)方法是屬于一個(gè)對(duì)象的函數(shù),被命名為 obj.methodname家凯,其中 obj 是某些對(duì)象(也可能是表達(dá)式)缓醋。而 methodname 是由對(duì)象類型確定的方法名。不同的對(duì)象確定不同的方法绊诲。不同對(duì)象的方法可能會(huì)有相同的方法名送粱,卻不會(huì)引起歧義。你可以是由 class 定義你自己的對(duì)象類型掂之。append 正是 list 對(duì)象的方法抗俄,它在 list 的末尾增加一個(gè)新元素脆丁,這等同于 result = result + [a],但是更加高效动雹。
更多關(guān)于定義函數(shù)的知識(shí)
默認(rèn)參數(shù)值
- 設(shè)定默認(rèn)值
- def ask_ok(prompt, retries=4, reminder=‘a(chǎn)gain’)
- 只給一個(gè)強(qiáng)制參數(shù)
- 給出一個(gè)可選參數(shù)
- 給出全部參數(shù)
- in 用于判斷一個(gè)序列是否有某個(gè)值
- 默認(rèn)值在函數(shù)定義前給出
i = 5
def f(arg=i):
print(arg)
i = 6
f()
# 打印 5
警告:
初始值只被計(jì)算一次偎快。這使得當(dāng)初始值是可變對(duì)象(列表,字典洽胶,或者大多數(shù)類)晒夹,會(huì)有一些不同。舉個(gè)例子姊氓,下面的函數(shù)會(huì)累計(jì)傳遞給序列的參數(shù)丐怯。
def f(a, L=[]):
L.append(a)
return L
print(f(1))
print(f(2))
print(f(3))
輸出:
[1]
[1, 2]
[1, 2, 3]
def f(a, L=None):
if L is None:
L = []
L.append(a)
return L
關(guān)鍵字(Keyword Arguments)
通過使用關(guān)鍵字參數(shù)(kwarg=value),我們可以調(diào)用函數(shù)翔横。
- 關(guān)鍵字參數(shù) 必須在位置參數(shù)之后
- 非關(guān)鍵字參數(shù)要在關(guān)鍵字參數(shù)之前
- 正確:12, state = ‘jump’
- 錯(cuò)誤:voltage = 12, ‘jump’
- 每個(gè)參數(shù)不能重復(fù)接受值
*arguments **keywords
- **name 接受字典 keyword = value return dict
- *name 接受元組包含所有的位置參數(shù)读跷,超出正式參數(shù)列表
- *name 必須在 **name 的前面
def f(*age,**name):
print(age)
print(name)
f(1,4,'sd',key = 'sd',time = '12')
任意參數(shù)列表
- 最后,最不常用的的選項(xiàng)可以用任意數(shù)目參數(shù)禾唁,這些參數(shù)將會(huì)被包裹在元組中效览,零個(gè)或者多個(gè)參數(shù)都可以。
- 可變參數(shù)(variadic)荡短,必須在正式參數(shù)的最后丐枉,因?yàn)樗鼈兘邮苁S嗨袀鬟f給函數(shù)的輸入?yún)?shù)
- 任何在 *arg 后面的參數(shù),必須是“keyword-only”參數(shù)掘托,也就是說瘦锹,必須以關(guān)鍵字的形式而不是位置參數(shù)形式使用關(guān)鍵字
def concat(*args, sep="/"):
print(sep.join(args))
concat("earth", "mars", "venus", sep=".")
concat("earth", "mars", "venus")
解包函數(shù)參數(shù)列表
相反的情況,就是參數(shù)已經(jīng)在列表或者元組中了闪盔,但是函數(shù)調(diào)用需要分離的位置參數(shù)弯院,這是我們就要將列表或者元組解包。舉個(gè)例子泪掀,內(nèi)置函數(shù) range 需要 start 和 stop 參數(shù)听绳。如果這些參數(shù)不能被分別得到,我們就要用到 * 操作符進(jìn)行解包來獲取列表或者元組中的參數(shù)异赫。相似的椅挣,我們可以使用 **dict 來獲取字典中元素。
a = {'name':'xkk', 'age':18, 'hobby': 'read'}
f(**a)
lambda 表達(dá)式
小型匿名(anonymous)函數(shù)祝辣,可以使用關(guān)鍵字 lambda贴妻。這個(gè)函數(shù)返回兩個(gè)關(guān)鍵字的和:lambda a, b: a+b。lambda 函數(shù)可以在需要函數(shù)對(duì)象的地方使用蝙斜。在語(yǔ)法上名惩,它被限制為單個(gè)表達(dá)式。從語(yǔ)義上講孕荠,它們正常定義函數(shù)的語(yǔ)法糖(syntactic sugar)娩鹉,類似于內(nèi)置函數(shù)定義攻谁,lambda 函數(shù)可以引用包含范圍內(nèi)的變量。
>>> pairs = [(1, 'one'), (2, 'two'), (3, 'three'), (4, 'four')]
>>> pairs.sort(key=lambda pair: pair[1])
>>> pairs
[(4, 'four'), (1, 'one'), (3, 'three'), (2, 'two')]
文檔說明
下面是一些關(guān)于說明文檔內(nèi)容與格式的慣例弯予。
第一行因該是對(duì)于對(duì)象目標(biāo)簡(jiǎn)短而準(zhǔn)確的介紹戚宦。簡(jiǎn)單地說,它不應(yīng)該明確說明對(duì)象的名字和類型锈嫩,因?yàn)檫@些可以通過其他方式介紹受楼,除非對(duì)象名碰巧是描述函數(shù)操作的動(dòng)詞。這一行應(yīng)該以大寫字母開頭呼寸,以句號(hào)結(jié)束艳汽。(end with a period)
如果說明文檔有多行,那么第二行應(yīng)該是空白行对雪,視覺上分割總結(jié)與其余部分河狐。接下來的內(nèi)容,應(yīng)該是一段或者更多段落瑟捣,描述調(diào)用慣例和副作用(side effects)馋艺。
Python 解釋器并不會(huì)從多行字符文字中去除縮進(jìn)。所以如果需要的話迈套,處理文本的工具必須去除縮進(jìn)捐祠。我們通過以下慣例實(shí)現(xiàn)。第一個(gè)行之后的第一個(gè)非空行確定整個(gè)文本的縮進(jìn)數(shù)目交汤。(我們不能使用第一行雏赦,因?yàn)樗ǔEc字符串的開頭引號(hào)相鄰,所以它的縮進(jìn)在文本中并不明顯)芙扎。所有行的字符串的開頭被去除與之相同的空白。缺少縮進(jìn)的行不應(yīng)該出現(xiàn)填大,但是所有行領(lǐng)先的空白應(yīng)該被去除戒洼。應(yīng)在擴(kuò)展標(biāo)簽后測(cè)試空格的有效性。
>>> def my_function():
... """Do nothing, but document it.
...
... No, really, it doesn't do anything.
... """
... pass
...
>>> print(my_function.__doc__)
Do nothing, but document it.
No, really, it doesn't do anything.
功能注釋(Function Annotations)
功能注釋關(guān)于用戶定義函數(shù)使用的類型的可選元數(shù)據(jù)信息允华。
注釋作為字典存儲(chǔ)在函數(shù)的__annotations__
屬性中圈浇,對(duì)函數(shù)的其他任何部分沒有任何影響。功能注釋被參數(shù)名后面的冒號(hào)所定義靴寂,后面可以用表達(dá)式表示參數(shù)值磷蜀。返回注釋有 –>
定義,后面是表達(dá)式百炬,在參數(shù)列表與表示 def 語(yǔ)句結(jié)束的冒號(hào)之間褐隆。下面的例子有一個(gè)位置參數(shù),一個(gè)關(guān)鍵字參數(shù)剖踊,并且返回值被注釋了庶弃。
def f(ham: str, eggs: str = 'eggs') -> str:
print("Annotations:", f.__annotations__)
print("Arguments:", ham, eggs)
return ham + ' and ' + eggs
f('spam')
間奏曲(intermezzo):代碼風(fēng)格
- 既然你準(zhǔn)備寫更長(zhǎng)衫贬、更復(fù)雜的 Python 代碼,我們很有必要來討論代碼的風(fēng)格歇攻。
- 大多數(shù)語(yǔ)言可以用多種風(fēng)格表示固惯,更準(zhǔn)確地說格式化。
- 一些的可讀性較強(qiáng)缴守,使你的代碼讓別人輕易地讀出來總是一個(gè)好主意葬毫,采用一種比較好地代碼風(fēng)格非常有幫助。
- 對(duì)于 Python 來說屡穗,PEP 8 已經(jīng)成為大多數(shù)項(xiàng)目接受的指導(dǎo)風(fēng)格贴捡,它提出一種可讀性強(qiáng),賞心悅目的代碼風(fēng)格鸡捐。每一個(gè) Python 開發(fā)者都應(yīng)該在某個(gè)時(shí)刻讀一下指南栈暇,下面是為你歸納出來的最重要的幾點(diǎn):
- 使用 4 個(gè)空格的縮進(jìn),而不是 tabs
四個(gè)空格在大小縮進(jìn)得到了平衡(縮進(jìn)短允許更大的嵌套深度箍镜,縮進(jìn)長(zhǎng)更易于閱讀)源祈,Tabs 會(huì)導(dǎo)致誤解,最好被省略色迂。
- 每一行不超過 79 個(gè)字符
這有助于用戶使用小型顯示器香缺,并且實(shí)現(xiàn)了在較大顯示器并排顯示代碼文件
- 使用空行去分隔函數(shù)與類和函數(shù)中較大的代碼塊
- 盡可能在每一行寫下他們的注釋
- 使用說明文檔、
- 在操作符和之后之后使用空格歇僧,但是不直接包圍結(jié)構(gòu):a = f(1, 2) + g(3, 4)
- 命名你的類與函數(shù)要一致图张,慣例是使用駝峰(CameCase)命名法命名類,小寫字母和下標(biāo)命名函數(shù)與方法诈悍』雎郑總是使用 self 作為方法的第一個(gè)參數(shù)。
- 不要使用花哨的編碼如果你的代碼要用在國(guó)際環(huán)境的話侥钳。Python 默認(rèn)使用 UTF-8 編碼适袜,或者純 ASCII 都能工作得很好。
- 同樣舷夺,不要在鑒定符使用非 ASCII 字符苦酱,如果只有最輕微的可能會(huì)有不同語(yǔ)言的人閱讀與維護(hù)代碼的話。
數(shù)據(jù)結(jié)構(gòu)
列表
- list.append(x)
在列表末尾增加元素给猾。等同于 a[len(a):] = [x]
- list.extend(iterable)
擴(kuò)展列表通過追加來自可迭代對(duì)象中的元素疫萤。等同于a[len(a):] = iterable
- list.insert(i, x)
在給定位置插入元素。第一個(gè)參數(shù)要插入元素的索引敢伸。所以a,insert(0, x)
在列表的最前面插入數(shù)據(jù)扯饶,而a.insert(len(a), x)
則等同于 a.append(x)
- list.remove(x)
刪除列表中第一次出現(xiàn)的值為 x 的數(shù)。如果沒有這個(gè)元素,會(huì)返回錯(cuò)誤帝际。
- list.pop([i])
刪除列表中給定位置的元素蔓同,然后返回這個(gè)元素。如果沒有說明索引蹲诀,a.pop()
會(huì)刪除并返回列表中的最后一個(gè)元素斑粱。(方法中 i 周圍的方括號(hào)說明參數(shù)是可選參數(shù),不是你應(yīng)該在那個(gè)位置敲上方括號(hào)脯爪,你將會(huì)看到這個(gè)記號(hào)在 Python 參考庫(kù)頻繁地出現(xiàn))
- list.clear()
從列表中刪除全部的元素则北,等同于 del a[:]
。a[:]相當(dāng)于是列表a 的淺拷貝痕慢,刪除a[:]就是刪除列表a中所有元素尚揣。如果使用 del a
,就相當(dāng)于刪除列表a掖举。
- list.index(x[,start[,end]])
返回在以零為列表首元素索引的列表中快骗,值為 x 的元素的索引。如果沒有該元素塔次,會(huì)產(chǎn)生 ValueError方篮。
可選參數(shù) start 和 end 用于限定搜索的子序列的開始與結(jié)束點(diǎn)。被返回的索引是相對(duì)于完整序列的開頭而不是由 start 參數(shù)計(jì)算出來的励负。
- list.count(x)
返回列表中 x 出現(xiàn)的次數(shù)藕溅。0:0
- list.sort(key=None,reverse=False)
給列表中的元素排序。
- list.reverse()
逆序继榆。
- list.copy()
返回 list 的淺拷貝巾表,就相當(dāng)于 a[:]
你可能注意到了,像insert
,remove
,sort
之類的方法只修改 list 中的元素略吨,不返回打印的值------他們只返回 None
集币。這是 Python 中所有可變數(shù)據(jù)結(jié)構(gòu)的設(shè)計(jì)理念。不支持 list.insert(0, 12).remove() 之類的連續(xù)操作翠忠。
作為棧使用
list 的方法使得我們非常輕松就可以把列表當(dāng)作棧使用惠猿,棧中最后被添加的元素是第一個(gè)出棧的元素。在棧的頂部添加元素负间,使用 append。從棧的頂部取走元素姜凄,使用 pop() 方法
作為隊(duì)列使用
我們也可以將列表當(dāng)作隊(duì)列使用政溃,其中先進(jìn)先出。但是态秧,對(duì)于這種情況董虱,列表并不是很高效。盡管在 list 末尾進(jìn)行的 append 和 pop 操作是快速的,但是在列表的頭部插入和刪除數(shù)據(jù)是緩慢的愤诱。因?yàn)槠渌脑匾灰粋€(gè)個(gè)的移動(dòng)云头。
為了補(bǔ)全隊(duì)列,使用·collections.deque
淫半,這種方法被設(shè)計(jì)快速而高效地從兩端刪除與添加元素溃槐。
from collections import deque
queue = deque([1,2,3])
queue.append(0)
queue.appendleft(8)
列表推導(dǎo)式
列表推導(dǎo)式提供了一種更簡(jiǎn)潔的方式創(chuàng)建列表。這常用于創(chuàng)建怎樣的新列表呢科吭?通常是列表中的元素是對(duì)其他序列或者可迭代變量的成員進(jìn)行一系列操作的結(jié)果昏滴。或者在一定條件下对人,創(chuàng)建這些元素的子序列谣殊。
squares = [x**2 for x in range(10)]
更加簡(jiǎn)潔,可讀性更強(qiáng)
列表推導(dǎo)式方括號(hào)中的表達(dá)式后面可以加上 for 語(yǔ)句牺弄,然后 0 個(gè)或者更多的 for 或者 if 語(yǔ)句姻几。結(jié)果將會(huì)是一個(gè)新列表,通過 for 或者 if 語(yǔ)句限定得到的表達(dá)式
[(x, y) for x in [1,2,3] for y in [3,1,4] if x != y]
表達(dá)式是元組必須括起來
# flatten
vec = [[1,2,3], [4,5,6], [7,8,9]]
[num for elem in vec for num in elem]
嵌套列表推導(dǎo)式
列表推導(dǎo)式的第一個(gè)表達(dá)式可以是任意的表達(dá)式势告,包括另一個(gè)列表推導(dǎo)式蛇捌。
[[row[i] for row in matrix] for i in range(4)]
list(zip(*matrix))
del 語(yǔ)句
- 有一種方式從列表中移除數(shù)值基于他的索引而不是基于他的數(shù)值
- 這不同于 pop 方法會(huì)返回刪除的值
- del 語(yǔ)句也被用于從列表中移除切片或者整個(gè)列表
- del 也可以刪除整個(gè)變量,這時(shí)再引用變量名 a 就會(huì)產(chǎn)生錯(cuò)誤(至少直到它被賦予新的值)
元組與序列
我們看到列表與字符串有許多共同的性質(zhì)培慌,比如索引與切片操作豁陆。他們都是序列數(shù)據(jù)類型。由于 Python 是一種不斷發(fā)展的語(yǔ)言吵护,其他序列數(shù)據(jù)類型也可能被增加盒音。Python 中存在其他標(biāo)準(zhǔn)序列數(shù)據(jù)類型:元組。
元組是由逗號(hào)隔開的值馅而,是不可改變量(immutable)祥诽,但是可以包含列表等可變對(duì)象。
正如你看到的瓮恭,輸出元組總是被括號(hào)包圍雄坪,所以嵌套元組總會(huì)被正確地解釋,盡管通常括號(hào)是不必要的(如果元組是更大表達(dá)式的一部分)屯蹦。不可能給元組單個(gè)元素賦值维哈,但是我們可以創(chuàng)建包含可變對(duì)象的元組。
盡管元組看上去與列表類似登澜,但他們通常被用于不同的場(chǎng)合為了不同的目的阔挠。元組是不可更改的,通常包含不同類型的序列脑蠕,這些序列可以通過解包或者索引來獲取购撼。列表是可變對(duì)象跪削,列表的元素通常是同類型的,可以通過迭代來獲取元素迂求。(元組也可以)
一個(gè)特殊的問題是包含一個(gè)或者零個(gè)元素的元組構(gòu)造:語(yǔ)法有特定的處理來適應(yīng)這些碾盐。空元組由一對(duì)空括號(hào)組成揩局,只有一個(gè)元素的元組毫玖,構(gòu)造為:數(shù)值加上逗號(hào)(將一個(gè)值括起來是不夠的)。很丑谐腰,但是有效孕豹。
解包:t = 1, 2, 3 x, y, z = t
序列解包,適用于右邊所有序列十气。序列解包要求励背,左邊的變量個(gè)數(shù)要與右邊序列元素個(gè)數(shù)相同。注意多變量賦值只是先將序列打包再解包的過程砸西。
集合
- 無序性
- 互異性
- 成員資格測(cè)試和去重
- 支持?jǐn)?shù)學(xué)操作:并叶眉,交,補(bǔ)芹枷,對(duì)等差分(symmetric difference)
- 大括號(hào)或者 set 函數(shù)用于產(chǎn)生集合衅疙。
- 空集,你必須使用 set() 函數(shù)鸳慈,空的大括號(hào){}會(huì)創(chuàng)建空子典
- fast membership testing : elem in set
- a - b in a not in b
- a ^ b in a or b but not both
- 和列表推導(dǎo)式類似饱溢,集合也支持推導(dǎo)式
a = {x for x in ‘a(chǎn)bracadabra’ if x not in ‘a(chǎn)bc’ }
字典
Python 內(nèi)置的另一個(gè)有用的數(shù)據(jù)類型是字典。字典有時(shí)在其他語(yǔ)言中被認(rèn)為是“associative memories” 或者是“associative arrays”走芋。不像序列可以被一些數(shù)字索引绩郎,字典是通過關(guān)鍵字索引,關(guān)鍵字可以是任何不可變量類型翁逞。字符串與數(shù)字總是可以作為關(guān)鍵字肋杖。元組可以被用作關(guān)鍵字,如果他們只包含字符串挖函、數(shù)字或者元組状植。如果一個(gè)元組直接或者間接地包含任何可變對(duì)象,那么他不可以用作關(guān)鍵字怨喘。你不能使用列表作為關(guān)鍵字津畸,因?yàn)槲覀兛梢允褂盟饕x值、切片賦值或者 append必怜、extend 等方式修改列表元素洼畅。
我們最好認(rèn)為字典是鍵值對(duì)的集合,前提條件是關(guān)鍵字都是互異的棚赔。空的大括號(hào)創(chuàng)建空子典。在大括號(hào)中使用逗號(hào)隔開鍵值對(duì)可以初始化字典靠益,這也是字典在輸出上的寫法丧肴。
字典的主要操作是存儲(chǔ)一些關(guān)鍵字并且基于關(guān)鍵字提取數(shù)值。我們也可以通 del 來刪除鍵值對(duì)胧后。如果你對(duì)一個(gè)已經(jīng)存在的關(guān)鍵字賦值芋浮,那么舊的關(guān)鍵字對(duì)應(yīng)的值將會(huì)被覆蓋。如果你使用不存在的關(guān)鍵字壳快,程序就會(huì)報(bào)錯(cuò)纸巷。
執(zhí)行 list(d) 會(huì)按原有順序返回字典中的所有關(guān)鍵字(如果你只想排序的話,使用 sorted(d) 代替)眶痰。為了檢驗(yàn)單個(gè)關(guān)鍵字是否在字典中瘤旨,我們可以使用 in 這個(gè)關(guān)鍵字。
dict() 可以從其他包含鍵值對(duì)的序列構(gòu)造字典竖伯。
dict([('sape', 4139), ('guido', 4127), ('jack', 4098)])
dict([['sape', 4139], ['guido', 4127], ['jack', 4098]])
字典推導(dǎo)式也支持任意的鍵值對(duì)表達(dá)式
{x: x**2 for x in (2, 4, 6)}
如果關(guān)鍵字是簡(jiǎn)單字符串存哲,有時(shí)使用關(guān)鍵字參數(shù)來說明鍵值對(duì)更加方便。
循環(huán)技巧
當(dāng)?shù)值鋾r(shí)七婴,我們通過 items() 方法可以同時(shí)取出關(guān)鍵字與對(duì)應(yīng)值祟偷。
迭代序列,使用 enumerate()打厘,我們可以同時(shí)得到位置索引和對(duì)應(yīng)值修肠。
為了同時(shí)迭代兩個(gè)或者更多的序列,我們可以使用 zip() 函數(shù)户盯。
為了以相反順序迭代嵌施,我們可以使用 reversed() 函數(shù) a[::-1]
為了按照順序迭代序列,使用 sorted() 函數(shù)先舷。該函數(shù)返回一個(gè)新的有序序列艰管,并保持源頭(被拷貝的序列)不變。
當(dāng)你迭代一個(gè)列表時(shí)蒋川,你很有可能改變了列表牲芋,所以更簡(jiǎn)單、更安全的方式是再新建一個(gè)列表捺球。