CH.15 函式基礎
要注意的概念有幾點
CH.16 範圍和引數
區域變數和廣域變數的簵圍的概念在 C 當中並不陌生, 不過在操作上有一些要注意的部份,因為python不需要宣告 variable 就可以開始使用,所以一但你在函式中把一個值指定給一個變數後,他就會生出一個 local variable,以下面這個例子為例,對 C programmer 來說,應該會印出 100,但在 python 來說,它其實已經建立了 local variable,所以 function 中存取的其實是 local variable,而不是 global variable,乍看之下會覺得有問題,但理解 python 是怎麼運作之後就不會覺得奇怪了
如果一定要改變 global variable,就必須加上 global 這個關鍵字
如果只是單獨要讀取 global variable,不一定要加上 global 關鍵字,只要你沒有宣告過同樣名字的 local variable ,它就會自動去上一層的區域找尋這個變數,這個還算顯然,和 C 沒什麼不同
不過我又改寫了 local 這個函式,一開始不太明白為什麼會有 error 訊息,到後來才明白一件事,我們不能把 python 的函式看成逐行執行的 script,而必須把它看成一個整體的東西,一但函式打包起來,它就會知道裡面有一個叫 var 的 local variable,所以其實第一行要印 var 時就會出問題,它會認為 var 還沒給過值是不能印的
工廠函式以前在 C 是個禁忌,因為一般都是病毒型的程式碼才會動態生成函式,聽說會自我變種的病毒也都是利用了類似的技巧,想不到在 Python 中可以輕易的實作出來。
書中的這個例子,說明了如果要大量製造函式時,引數必須要以預設值傳進新函式中,否則製造出來的函式都會是長的一樣的,對於這個例子我看了很久,最後我對於他的解讀是新函式中的 i 因為找不到對應的 local variable ,所以會被強迫指向 makeActions 中的 i,也就是說所有新生成的函式都會指向同一個 i ,才會造成執行結果都一樣。書中用 "實質上都是記住相同之值" 來描述這件事其實讓我一開始無法理解,如果用 "指標指向同一個變數" 來講,可能就會更清楚。
記得在 C 當中在處理任意引數是很麻煩的,我曾經想要做一件事,就是把 funcA 的任意引數再傳進 funcB,結果我花了很多時間研究有沒有辦法做到,發現似乎沒有解,到現在我仍然不知道要怎麼做,但在 Python 當中這件事真的是簡單到不行,不得不佩服 Python 設計者的巧思
CH.17 高等函式議題
在第十六章看到 lambda 時還無法理解為什麼要有這個東西,覺得它的功用和 function 沒什麼兩樣,但看到第十七章的說明後,這讓我想到 Java 裡面有 Anonymous inner classes,感覺有異曲同工之妙,同樣都是為了省下宣告新的 class ,把 class 及使用 function/class 的人緊緊的綁在一起。
apply, filter, reduce 跳過不看
list comprehension 的語法要記熟!
[expression for target1 in sequence1 [if condition1]
for target2 in sequence2 [if condition2]
for target3 in sequence3 [if condition3] ... ]
然後記下一個二維矩陣的用法,和一般用法不同
2012.03.24 補:
因為實在太重要了, 但又常忘記要怎麼用, 留幾個 sample link
http://docs.python.org/reference/expressions.html?highlight=list%20comprehension#list-displays
http://www.secnetix.de/olli/Python/list_comprehensions.hawk
http://docs.python.org/tutorial/datastructures.html#list-comprehensions
http://www.bogotobogo.com/python/python_list_comprehension.html
可變更預設引數在函式呼叫之間會保留其狀態,這一點我真的覺得太奇怪了,真的很容易造成陷阱,一般來說程式設計者預設應該不是想要這種功能才對呀~ 早就己經習慣固定的參數輸入值會得到固定的結果的我,實在不太能接受這點,這真的要好好記一下
要注意的概念有幾點
- def 是可執行的程式碼,它並不是宣告而已,也不是 Macro,它其實做的事情是把一段程式碼打包成一個函式物件,然後傳給函式變數,之後我們可以透過這個函式變數來執行這段程式碼,所以他甚至是可以動態決定這段程式碼要長成什麼樣子
if test: def func(): ... else: def func(): .... ... func()
CH.16 範圍和引數
區域變數和廣域變數的簵圍的概念在 C 當中並不陌生, 不過在操作上有一些要注意的部份,因為python不需要宣告 variable 就可以開始使用,所以一但你在函式中把一個值指定給一個變數後,他就會生出一個 local variable,以下面這個例子為例,對 C programmer 來說,應該會印出 100,但在 python 來說,它其實已經建立了 local variable,所以 function 中存取的其實是 local variable,而不是 global variable,乍看之下會覺得有問題,但理解 python 是怎麼運作之後就不會覺得奇怪了
>>> def local(): var = 100 >>> var = 0 >>> local() >>> print var 0
如果一定要改變 global variable,就必須加上 global 這個關鍵字
>>> def local(): global var var = 100 >>> var = 0 >>> local() >>> print var 100
如果只是單獨要讀取 global variable,不一定要加上 global 關鍵字,只要你沒有宣告過同樣名字的 local variable ,它就會自動去上一層的區域找尋這個變數,這個還算顯然,和 C 沒什麼不同
>>> def local(): print var >>> var = 100 >>> local() 100
不過我又改寫了 local 這個函式,一開始不太明白為什麼會有 error 訊息,到後來才明白一件事,我們不能把 python 的函式看成逐行執行的 script,而必須把它看成一個整體的東西,一但函式打包起來,它就會知道裡面有一個叫 var 的 local variable,所以其實第一行要印 var 時就會出問題,它會認為 var 還沒給過值是不能印的
>>> def local(): print var # 我覺得應該要印出 global variable var = 100 # 生成 local variable print var # 我覺得應該要印出 local variable >>> var = 100 >>> local() Traceback (most recent call last): File "", line 1, in local() File " ", line 2, in local print var UnboundLocalError: local variable 'var' referenced before assignment >>>
工廠函式以前在 C 是個禁忌,因為一般都是病毒型的程式碼才會動態生成函式,聽說會自我變種的病毒也都是利用了類似的技巧,想不到在 Python 中可以輕易的實作出來。
書中的這個例子,說明了如果要大量製造函式時,引數必須要以預設值傳進新函式中,否則製造出來的函式都會是長的一樣的,對於這個例子我看了很久,最後我對於他的解讀是新函式中的 i 因為找不到對應的 local variable ,所以會被強迫指向 makeActions 中的 i,也就是說所有新生成的函式都會指向同一個 i ,才會造成執行結果都一樣。書中用 "實質上都是記住相同之值" 來描述這件事其實讓我一開始無法理解,如果用 "指標指向同一個變數" 來講,可能就會更清楚。
>>> def makeActions(): acts = [] for i in range(5): acts.append(lambda x: i ** x) return acts >>> acts = makeActions() >>> acts[0](2) 16 >>> acts[1](2) 16
記得在 C 當中在處理任意引數是很麻煩的,我曾經想要做一件事,就是把 funcA 的任意引數再傳進 funcB,結果我花了很多時間研究有沒有辦法做到,發現似乎沒有解,到現在我仍然不知道要怎麼做,但在 Python 當中這件事真的是簡單到不行,不得不佩服 Python 設計者的巧思
int sum(int count, ...) { va_list ap; int j; int tot = 0; va_start(ap, count); tot = va_arg(ap, int); /* 把第一個取出來 */ va_end(ap); return tot + sum(count - 1, ...?? ) /* 想要用遞迴的方式算出剩下的加總,但這裡不知道要填什麼 */ }
def sum(*args): len_of_args = len(args) if len_of_args == 1: return args[0] if len_of_args == 0: return 0 return sum(*args[0:len_of_args/2]) + sum(*args[len_of_args/2:]) /* 輕易的把變動參數傳給下一個函式 */
CH.17 高等函式議題
在第十六章看到 lambda 時還無法理解為什麼要有這個東西,覺得它的功用和 function 沒什麼兩樣,但看到第十七章的說明後,這讓我想到 Java 裡面有 Anonymous inner classes,感覺有異曲同工之妙,同樣都是為了省下宣告新的 class ,把 class 及使用 function/class 的人緊緊的綁在一起。
button1.addActionListener( new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent e) { // do something } } );
apply, filter, reduce 跳過不看
list comprehension 的語法要記熟!
[expression for target1 in sequence1 [if condition1]
for target2 in sequence2 [if condition2]
for target3 in sequence3 [if condition3] ... ]
然後記下一個二維矩陣的用法,和一般用法不同
[[M[row][col] * N[row][col] for col in range(3)] for row in range(3)]
2012.03.24 補:
因為實在太重要了, 但又常忘記要怎麼用, 留幾個 sample link
http://docs.python.org/reference/expressions.html?highlight=list%20comprehension#list-displays
http://www.secnetix.de/olli/Python/list_comprehensions.hawk
http://docs.python.org/tutorial/datastructures.html#list-comprehensions
http://www.bogotobogo.com/python/python_list_comprehension.html
可變更預設引數在函式呼叫之間會保留其狀態,這一點我真的覺得太奇怪了,真的很容易造成陷阱,一般來說程式設計者預設應該不是想要這種功能才對呀~ 早就己經習慣固定的參數輸入值會得到固定的結果的我,實在不太能接受這點,這真的要好好記一下
>>> def saver (x=[]): x.append(1) print x >>> saver() [1] >>> saver() [1, 1]
沒有留言:
張貼留言