盤一盤 Python 系列 1 & 2 - 入門篇python
- 經過 dir( X ) 和help( X ) 可看出 X 對應的對象裏可用的屬性和方法。
- getcontext() 顯示了 Decimal 對象的默認精度值是 28 位 (prec=28)
- 那保留 4 位呢?用 getcontext().prec 來調整精度哦。
- decimal.getcontext().prec = 4
- 高精度的 float 加上低精度的 float,保持了高精度,沒毛病。
- 肯定bool(X) 的值是 True 仍是 False,就看 X 是否是空,空的話就是 False,不空的話就是 True。
- 對於數值變量,0, 0.0 均可認爲是空的。
- 對於容器變量,裏面沒元素就是空的。
- 字符中常見的內置方法 (能夠用 dir(str) 來查) 有
- capitalize():大寫句首的字母
- split():把句子分紅單詞
- find(x):找到給定詞 x 在句中的索引,找不到返回 -1
- replace(x, y):把句中 x 替代成 y
- strip(x):刪除句首或句末含 x 的部分
- pattern = re.compile("'[0-9/:\s]+'")
- 這個抽象模式表達式 '[0-9/:\s]+',裏面符號的意思以下:
- 最外面的兩個單引號 ' 表明該模式以它們開始和結束
- 中括號 [] 用來歸納該模式涵蓋的全部類型的字節
- 0-9 表明數字類的字節
- / 表明正斜線
- : 表明分號
- \s 表明空格
- [] 外面的加號 + 表明 [] 裏面的字節出現至少 1 次
- pattern.findall(input)
- 建立元組能夠用小括號 (),也能夠什麼都不用,爲了可讀性,建議仍是用 ()。此外對於含單個元素的元組,務必記住要多加一個逗號,舉例以下:
- print( type( ('OK') ) ) # 沒有逗號 , <class 'str'>
- print( type( ('OK',) ) ) # 有逗號 , <class 'tuple'>
- 看看,沒加逗號來建立含單元素的元組,Python 認爲它是字符。
- 固然也能夠建立二維元組:
- nested = (1, 10.31, 'python'), ('data', 11) # ((1, 10.31, 'python'), ('data', 11))
- 元組有不可更改 (immutable) 的性質,所以不能直接給元組的元素賦值
- t = ('OK', [1, 2], True)
- t[2] = False # TypeError: 'tuple' object does not support item assignment
- 可是隻要元組中的元素可更改 (mutable),那麼咱們能夠直接更改其元素,注意這跟賦值其元素不一樣。
- t[1].append(3) # ('OK', [1, 2, 3], True)
- 元組大小和內容都不可更改,所以只有 count 和 index 兩種方法。
- 元組拼接 (concatenate) 有兩種方式,用「加號 +」和「乘號 *」,前者首尾拼接,後者複製拼接。
- (1, 10.31, 'python') + ('data', 11) + ('OK',) # (1, 10.31, 'python', 'data', 11, 'OK')
- (1, 10.31, 'python') * 2 # (1, 10.31, 'python', 1, 10.31, 'python')
- 解壓 (unpack) 一維元組 (有幾個元素左邊括號定義幾個變量)
- t = (1, 10.31, 'python')
- (a, b, c) = t
- print( a, b, c ) # 1 10.31 python
- 解壓二維元組 (按照元組裏的元組結構來定義變量)
- t = (1, 10.31, ('OK','python'))
- (a, b, (c,d)) = t
- print( a, b, c, d ) # 1 10.31 OK python
- 若是你只想要元組其中幾個元素,用通配符「*」,英文叫 wildcard,在計算機語言中表明一個或多個元素。下例就是把多個元素丟給了 rest 變量。
- t = 1, 2, 3, 4, 5
- a, b, *rest, c = t
- print( a, b, c ) # 1 2 5
- print( rest ) # [3, 4]
若是你根本不在意 rest 變量,那麼就用通配符「*」加上下劃線「_」,例子以下:
- a, b, *_ = t
- print( a, b ) # 1 2
- tuple優勢缺點
- 優勢:佔內存小,安全,建立遍歷速度比列表快,可一賦多值。
- 缺點:不能添加和更改元素。
- immutable 的好處實在是太多了:性能優化,多線程安全,不須要鎖,不擔憂被惡意修改或者不當心修改。
- tuple v.s. list
- 建立速度,元組 (12.9ns) 碾壓列表 (62ns)。
- 遍歷速度二者至關,元組 (498 µs) 險勝列表 (507 µs)。
- 列表比元組稍微廢點內存空間。
- 不像元組,列表內容可更改 (mutable),所以附加 (append, extend)、插入 (insert)、刪除 (remove, pop) 這些操做均可以用在它身上。
- l.append([4, 3])
- print( l ) # [1, 10.31, 'python', [4, 3]]
- l.extend([1.5, 2.0, 'OK'])
- print( l ) # [1, 10.31, 'python', [4, 3], 1.5, 2.0, 'OK']
- 嚴格來講 append 是追加,把一個東西總體添加在列表後,而 extend 是擴展,把一個東西里的全部元素添加在列表後。對着上面結果感覺一下區別。
- insert(i, x) 在編號 i 位置前插入 x。
- remove 和 pop 均可以刪除元素
- 前者是指定具體要刪除的元素,好比 'python'
- 後者是指定一個編號位置,好比 3,刪除 l[3] 並返回出來
- print( l[::-1] )
- 注意最後把 step 設爲 -1,至關於將列表反向排列。
- 和元組拼接同樣, 列表拼接也有兩種方式,用「加號 +」和「乘號 *」,前者首尾拼接,後者複製拼接。
- list優勢缺點
- 優勢:靈活好用,可索引、可切片、可更改、可附加、可插入、可刪除。
- 缺點:相比 tuple 建立和遍歷速度慢,佔內存。此外查找和插入時間較慢。
- 字典裏最經常使用的三個內置方法就是 keys(), values() 和 items(),分別是獲取字典的鍵、值、對。
- 此外在字典上也有添加、獲取、更新、刪除等操做。
- 好比想看看騰訊的股價是多少 (兩種方法均可以)
- print( d['Price'] )
- print( d.get('Price') )
- 好比去掉股票代碼 (code)
- 或像列表裏的 pop() 函數,刪除行業 (industry) 並返回出來。
- print( d.pop('Industry') )
- 字典裏的鍵是不可更改的,所以只有那些不可更改的數據類型才能當鍵,好比整數 (雖然怪怪的)、浮點數 (雖然怪怪的)、布爾 (雖然怪怪的)、字符、元組 (雖然怪怪的),而列表卻不行,由於它可更改。
- 雖然怪怪的,但這些 2, 10.31, True, ('OK', 3) 確實能當鍵。有個地方要注意下,True 其實和整數 1 是同樣的,因爲鍵不能重複,當你把 2 該成 1時,你會發現字典只會取其中一個鍵,示例以下:
- d = {
- 1 : 'integer key',
- 10.31 : 'float key',
- True : 'boolean key',
- ('OK',3) : 'tuple key'
- }
- # d
- {1: 'boolean key',
- 10.31: 'float key',
- ('OK', 3): 'tuple key'}
- 那麼如何快速判斷一個數據類型 X 是否是可更改的呢?兩種方法:
- 麻煩方法:用 id(X) 函數,對 X 進行某種操做,比較操做先後的 id,若是不同,則 X 不可更改,若是同樣,則 X 可更改。
- 便捷方法:用 hash(X),只要不報錯,證實 X 可被哈希,即不可更改,反過來不可被哈希,便可更改。
- dictionary優勢缺點
- 集合有兩種定義語法
- 第一種是
- 第二種是用 set() 函數,把列表或元組轉換成集合。
- 從A的結果發現集合的兩個特色:無序(unordered)和惟一(unique)。因爲set存儲的是無序集合,因此咱們無法經過索引來訪問,可是能夠判斷一個元素是否在集合中。
- 用 set 的內置方法就把它當成是數學上的集,那麼並集、交集、差集均可以玩通了。
- 並集 OR
- print( A.union(B) ) # All unique elements in A or B
- print( A | B ) # A OR B
- 交集 AND
- print( A.intersection(B) ) # All elements in both A and B
- print( A & B ) # A AND B
- 差集 A - B
- print( A.difference(B) ) # Elements in A but not in B
- print( A - B ) # A MINUS B
- 差集 B - A
- print( B.difference(A) ) # Elements in B but not in A
- print( B - A ) # B MINUS A
- 對稱差集 XOR
- print( A.symmetric_difference(B) ) # All elements in either A or B, but not both
- print( A ^ B ) # A XOR B
- set優勢缺點
- if-elif-else 語句
- 對於迭代循環,Python 裏面有「while 循環」和「for 循環」,沒有「do-while 循環」。
- 通用形式的 for loop 以下
- for a in A
- 其中 for 和 in 是關鍵詞,A 是個可迭代數據 (list, tuple, dic, set),a 是 A 裏面的每一個元素
- 最後介紹一個稍微有點特殊的函數 enumerate(),和 for loop 一塊兒用的語法以下
- for i, a in enumerate(A)
- 發現區別了沒?用 enumerate(A) 不只返回了 A 中的元素,還順便給該元素一個索引值 (默認從 0 開始)。此外,用 enumerate(A, j) 還能夠肯定索引發始值爲 j。
- languages = ['Python', 'R', 'Matlab', 'C++']
- for i, language in enumerate(languages, 1):
- print( i, 'I love', language )
- print( 'Done!' )
- # 1 I love Python
- 2 I love R
- 3 I love Matlab
- 4 I love C++
- Done!
- 數據類型分兩種:
- 單獨類型:整型、浮點型、布爾型
- 容器類型:字符、元組、列表、字典、集合
- Python 的函數具備很是靈活多樣的參數形態。從簡到繁的參數形態以下:
- 位置參數 (positional argument)
- 默認參數 (default argument)
- 可變參數 (variable argument)
- 關鍵字參數 (keyword argument)
- 命名關鍵字參數 (name keyword argument)
- 參數組合
- 位置參數
- arg1 - 位置參數 ,這些參數在調用函數 (call function) 時位置要固定。
- 默認參數
- arg2 = v - 默認參數 = 默認值,調用函數的時候,默認參數已經有值,就不用再傳值了。
- 默認函數必定要放在位置參數後面,否則程序會報錯。
- 在調用參數把它的「關鍵字」也帶上,咱們就能夠隨便調換參數的順序。
- 可變參數
- *args - 可變參數,能夠是從零個到任意個,自動組裝成元組。
- 可變參數用兩種方式傳入
- 直接傳入,func(1, 2, 3)
- 先組裝列表或元組,再經過 *args 傳入,func(*[1, 2, 3]) 或 func(*(1, 2, 3))
- 關鍵字參數
- **kw - 關鍵字參數,能夠是從零個到任意個,自動組裝成字典。
- 「可變參數」和「關鍵字參數」的同異總結以下:
- 可變參數容許傳入零個到任意個參數,它們在函數調用時自動組裝爲一個元組 (tuple)
- 關鍵字參數容許傳入零個到任意個參數,它們在函數內部自動組裝爲一個字典 (dict)
- 若是不傳入任何「關鍵字參數」,kw 爲空集。
- 除了直接傳入多個參數以外,還能夠將全部參數先組裝成字典 Conv,用以「**Conv」的形式傳入函數 (Conv 是個字典,前面加個通配符 ** 是拆散字典,把字典的鍵值對傳入函數中)
1 # =============================================================================
2 # id: MM1001
3 # notional: 10
4 # reporting currency: EUR
5 # present value: 150
6 # keyword: {'dc': 'act/365', 'bdc': 'following'}
7 # =============================================================================
8 DCF = (1, 2, 3, 4, 5)
9 Conv = {'dc':'act/365', 'bdc':'following'}
10 instrument5( 'MM1001', 10, 'EUR', *DCF, **Conv )
- 命名關鍵字參數
- *, nkw - 命名關鍵字參數,用戶想要輸入的關鍵字參數,定義方式是在nkw 前面加個分隔符 *。
- 若是要限制關鍵字參數的名字,就能夠用「命名關鍵字參數」
- 使用命名關鍵字參數時,要特別注意不能缺乏參數名。
1 def instrument6( id, ntl=1, curR='CNY', *, ctp, **kw ):
2 print( 'id:', id )
3 print( 'notional:', ntl )
4 print( 'reporting currency:', curR )
5 print( 'counterparty:', ctp )
6 print( 'keyword:', kw)
7
8 # =============================================================================
9 # id: MM1001
10 # notional: 100
11 # reporting currency: EUR
12 # counterparty: GS
13 # keyword: {'dc': 'act/365'}
14 # =============================================================================
15 instrument6( 'MM1001', 100, 'EUR',
16 dc='act/365', ctp='GS' )
17
18 # =============================================================================
19 # TypeError: instrument6() takes from 1 to 3
20 # positional arguments but 4 were given
21 # =============================================================================
22 instrument6( 'MM1001', 100, 'EUR',
23 'GS', dc='act/365' )

- 參數組合
- 在 Python 中定義函數,能夠用位置參數、默認參數、可變參數、命名關鍵字參數和關鍵字參數,這 5 種參數中的 4 個均可以一塊兒使用,可是注意,參數定義的順序必須是:
- 位置參數、默認參數、可變參數和關鍵字參數。
- 位置參數、默認參數、命名關鍵字參數和關鍵字參數。
- 要注意定義可變參數和關鍵字參數的語法:
- *args 是可變參數,args 接收的是一個 tuple
- **kw 是關鍵字參數,kw 接收的是一個 dict
- 命名關鍵字參數是爲了限制調用者能夠傳入的參數名,同時能夠提供默認值。定義命名關鍵字參數不要忘了寫分隔符 *,不然定義的是位置參數。
- 警告:雖然能夠組合多達 5 種參數,但不要同時使用太多的組合,不然函數很難懂。
- 匿名函數
- 在 Python 裏有兩種函數
- 用 def 關鍵詞的正規函數
- 用 lambda 關鍵詞的匿名函數
- lambda *args: sum(args);輸入是任意個數的參數,輸出是它們的和
- lambda **kwargs: 1;輸入是任意鍵值對參數,輸出是 1
- 對於 lambda 函數,有時咱們會過用 (overuse) 它或誤用 (misuse) 它。
- Misuse
- 誤用狀況:若是用 lambda 函數只是爲了賦值給一個變量,用 def 的正規函數。
- <function <lambda> at 0x000001997AA721E0>
- <function sqr at 0x000001997AA72268>
- lbd_sqr 的返回值是以 <lambda> 標識的函數,而 sqr 的返回時是以 sqr 爲標識的函數,明顯後者一看就知道該函數是「計算平方」用的。
- Overuse
- 過用狀況:若是一個函數很重要,它須要一個正規的名字。
- sorted(colors, key=lambda c: (len(c), c.casefold()))
- 坦白的說,這樣用 lambda 函數看起來是很酷,可是增長了使用者的「思考成本」,用 def 顯性定義個函數可讀性會好不少。
- 用正規函數還能加個函數說明 (docstring),再起個描述性強的函數名,讓人一看就知道該函數作什麼。
- 高階函數
- 高階函數 (high-order function) 在函數化編程 (functional programming) 很常見,主要有兩種形式:
- 參數是函數 (map, filter, reduce)
- 返回值是函數 (closure, partial, currying)
- Map, Filter, Reduce
- Python 裏面的 map, filter 和 reduce 屬於第一種高階函數,參數是函數。
- map(函數 f, 序列 x):對序列 x 中每一個元素依次執行函數 f,將 f(x) 組成一個「map 對象」返回 (能夠將其轉換成 list 或 set)
- filter(函數 f, 序列 x):對序列 x 中每一個元素依次執行函數 f,將 f(x) 爲 True 的結果組成一個「filter 對象」返回 (能夠將其轉換成 list 或 set)
- reduce(函數 f, 序列 x):對序列 x 的第一個和第二個元素執行函數 f,獲得的結果和序列 x 的下一個元素執行函數 f,一直遍歷完的序列 x 全部元素。
- map_iter = map( lambda x: x**2, lst ) # <map object at 0x0000018C83E72390>
- 注意 map_iter 是 map 函數的返回對象 (它是一個迭代器),想要將其內容顯示出來,須要用 list 將其轉換成「列表」形式。
- 惰性求值 (lazy evaluation) 也稱爲傳需求調用 (call-by-need),目的是最小化計算機要作的工做。
- 在上例中,map 函數做用到列表,並不會當即進行求平方,而是當你用到其中某些元素時纔去求平方。惰性是指,你不主動去遍歷它,就不會計算其中元素的值。
- 爲何要有 「惰性求值」呢?在本例看起來毫無必要,但試想大規模數據時,一次性處理每每抵消並且不方便,而惰性求值解決了這個問題,它把計算的具體步驟延遲到了要實際用該數據的時候。
- 惰性序列能夠看做是一個流 (flow),須要的時候從其中取一滴水。
- filter_iter = filter(lambda n: n % 2 == 1, lst)
- 一樣,filter_iter 做爲 filter 函數的返回對象,也是一個迭代器,想要將其內容顯示出來,須要用 list 將其轉換成「列表」形式。
- 最後來看看 reduce 函數,顧名思義就是累積函數,把一組數減小 (reduce) 到一個數。
- 在 reduce 函數的第三個參數還能夠賦予一個初始值,這是累積從 100 和列表 lst = [1,2,3,4,5] 的第一個元素 1 開始,一直加到整個 lst 元素遍歷完,所以最後求和爲 115。
1 from functools import reduce
2
3 lst = [1, 2, 3, 4, 5]
4
5 reduce( lambda x,y: x+y, lst ) # 15
6
7 reduce( lambda x,y: x+y, lst, 100 ) # 115
-
-
- 小結一下,對於 map, filter 和 reduce,好消息是,Python 支持這些基本的操做;而壞消息是,Python 不建議你使用它們。下節的「解析式」能夠優雅的替代 map 和 filter。
- 除了 Python 這些內置函數,咱們也能夠本身定義高階函數,以下:
1 def apply_to_list( fun, some_list ):
2 return fun(some_list)
3
4 lst = [1, 2, 3, 4, 5]
5
6 print( apply_to_list( sum, lst ) ) # 15
7
8 print( apply_to_list( len, lst ) ) # 5
9
10 print( apply_to_list( lambda x:sum(x)/len(x), lst ) ) # 3.0
- 閉包
- Python 裏面的閉包 (closure) 屬於第二種高階函數,返回值是函數。下面是一個閉包函數。
- 此函數的做用是作一個計數器,能夠
- 用增長子函數 inc() 續一秒
- 用減小子函數 dec() 廢一秒
- 用獲取子函數 get() 看秒數
- 用重置子函數 reset() 回原點
- 屬於第二類 (返回值是函數) 的高階函數還有「偏函數」和「柯里化」
1 def make_counter(init):
2 counter = [init]
3
4 def inc(): counter[0] += 1
5 def dec(): counter[0] -= 1
6 def get(): return counter[0]
7 def reset(): counter[0] = init
8
9 return inc, dec, get, reset
10
11 inc, dec, get, reset = make_counter(0)
12
13 inc()
14 inc()
15 inc()
16
17 get() # 3
- 偏函數
- 偏函數 (paritial function) 主要是把一個函數的參數 (一個或多個) 固定下來,用於專門的應用上 (specialized application)。要用偏函數用從 functools 中導入 partial 包
- 咱們知道 sort 函數默認是按升序排列,假設在你的應用中是按降序排列,你能夠把函數裏的 reverse 參數設置爲 True。這樣每次設定參數很麻煩,你能夠專門爲「降序排列」的應用定義一個函數,好比叫 sorted_dec,用偏函數 partial 把內置的 sort 函數裏的 reverse 固定住,代碼以下:
1 from functools import partial
2
3 lst = [3, 1, 2, 5, 4]
4
5 sorted( lst ) # [1, 2, 3, 4, 5]
6
7 sorted( lst, reverse=True ) # [5, 4, 3, 2, 1]
8
9 sorted_dec = partial( sorted, reverse=True )
10
11 sorted_dec # functools.partial(<built-in function sorted>, reverse=True)
12
13 sorted_dec( lst ) # [5, 4, 3, 2, 1]
-
- 小結,當函數的參數個數太多,須要簡化時,使用 functools.partial 能夠建立一個新的函數,即偏函數,它能夠固定住原函數的部分參數,從而在調用時更簡單。
- 柯里化
- 最簡單的柯里化 (currying) 指的是將原來接收 2 個參數的函數 f(x, y) 變成新的接收 1 個參數的函數 g(x) 的過程,其中新函數 g = f(y)。
- 經過嵌套函數能夠把函數 add1 轉換成柯里化函數 add2。
- 仔細看看函數 add1 和 add2 的參數
- add1:參數是 x 和 y,輸出 x + y
- add2:參數是 x,輸出 x + y
- g = add2(2):參數是 y,輸出 2 + y
- 比較「普通函數 add1」和「柯里化函數 add2」的調用,結果都同樣。
1 def add1(x, y):
2 return x + y
3
4 def add2(x):
5 def add(y):
6 return x + y
7 return add
8
9 add1 # <function __main__.add1(x, y)>
10
11 add2 # <function __main__.add2(x)>
12
13 g = add2(2)
14 g # <function __main__.add2.<locals>.add(y)>
15
16 print( add1(2, 3) ) # 5
17
18 print( add2(2)(3) ) # 5
19
20 print( g(3) ) # 5
- 解析式
- 大框架
- 解析式 (comprehension) 是將一個可迭代對象轉換成另外一個可迭代對象的工具。
- 上面出現了兩個可迭代對象 (iterable),不嚴謹地說,容器類型數據 (str, tuple, list, dict, set) 都是可迭代對象。
- 第一個可迭代對象:能夠是任何容器類型數據。
- 第二個可迭代對象:看是什麼類型解析式:
- 列表解析式:可迭代對象是 list
- 字典解析式:可迭代對象是 dict
- 集合解析式:可迭代對象是 set
1 # list comprehension
2 [值 for 元素 in 可迭代對象 if 條件]
3
4 # dict comprehension
5 {鍵值對 for 元素 in 可迭代對象 if 條件}
6
7 # set comprehension
8 {值 for 元素 in 可迭代對象 if 條件}


-
-
- 再回顧下三種解析式,咱們發現其實它們均可以實現上節提到的 filter 和 map 函數的功能,用專業計算機的語言說,解析式能夠當作是 filter 和 map 函數的語法糖。
- 語法糖 (syntactic sugar):指計算機語言中添加的某種語法,對語言的功能沒有影響,可是讓程序員更方便地使用。
- 語法鹽 (syntactic salt):指計算機語言中添加的某種語法,使得程序員更難寫出壞的代碼。
- 語法糖漿 (syntactic syrup):指計算機語言中添加的某種語法,沒能讓編程更加方便。
- 首先發現二者都是把原列表根據某些條件轉換成新列表,再者
- 「列表解析式」用 if 條件來作篩選獲得 item,再用 f 函數做用到 item 上。
- 「map/filter」用 filter 函數來作篩選,再用 map 函數做用在篩選出來的元素。
- 爲了達到相同目的,明顯「列表解析式」是種更簡潔的方式。
- 小例子
- 問題:用解析式將二維元組裏每一個元素提取出來並存儲到一個列表中。若是咱們想把上面「二維元組」轉換成「二維列表」呢?
1 tup = ((1, 2, 3), (4, 5, 6), (7, 8, 9))
2
3 flattened = [x for t in tup for x in t]
4
5 flattened # [1, 2, 3, 4, 5, 6, 7, 8, 9]
6
7 [ [x for x in t] for t in tup ] # [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
-
-
- 問題:用解析式把如下這個不規則的列表 a 打平 (flatten)?
- 用解析式一步到位解決上面問題有點難,特別是列表 a 不規則,每一個元素還能夠是 n 層列表,所以咱們須要遞推函數 (recursive function),即一個函數裏面又調用本身。
- 正規 (遞推) 函數寫好了,把它寫成匿名函數也很簡單了。
1 a = [1, 2, [3, 4], [[5, 6], [7, 8]]]
2
3 def f(x):
4 if type(x) is list:
5 return [y for l in x for y in f(l)]
6 else:
7 return [x]
8
9 f(a) # [1, 2, 3, 4, 5, 6, 7, 8]
10
11
12 a = [1, 2, [3, 4], [[5, 6], [7, 8]]]
13
14 f = lambda x: [y for l in x for y in f(l)] if type(y) is list else [x]
15
16 f(a) # [1, 2, 3, 4, 5, 6, 7, 8]
-
-
- 優雅清晰是 python 的核心價值觀,高階函數和解析式都符合這個價值觀。
- 函數包括正規函數 (用 def) 和匿名函數 (用 lambda),函數的參數形態也多種多樣,有位置參數、默認參數、可變參數、關鍵字參數、命名關鍵字參數。匿名函數主要用在高階函數中,高階函數的參數能夠是函數 (Python 裏面內置 map/filter/reduce 函數),返回值也能夠是參數 (閉包、偏函數、柯里化函數)。
- 解析式並無解決新的問題,只是以一種更加簡潔,可讀性更高的方式解決老的問題。解析式能夠把「帶 if 條件的 for 循環」用一行程序表達出來,也能夠實現 map 加 filter 的功能。
- 最後用 Tim Peters 的 The Zen of Python 結尾。
- Beautiful is better than ugly.
- Explicit is better than implicit.
- Simple is better than complex.
- Complex is better than complicated.
- Flat is better than nested.
- Sparse is better than dense.
- Readability counts.
- Special cases aren't special enough to break the rules.
- Although practicality beats purity.
- Errors should never pass silently.
- Unless explicitly silenced.
- In the face of ambiguity, refuse the temptation to guess.
- There should be one -- and preferably only one -- obvious way to do it.
- Although that way may not be obvious at first unless you're Dutch.
- Now is better than never.
- Although never is often better than right now.
- If the implementation is hard to explain, it's a bad idea.
- If the implementation is easy to explain, it may be a good idea.
- Namespaces are one honking great idea -- let's do more of those!