對于程序員學習來說,demo是很重要的,只要所講的知識點有了demo,就會變得很容易理解,此處我也是使用這種方法。
知識點一
一般來說,內建的callable函數可以用來判斷函數是否可調用。
>>> import math
>>> x = 1
>>> y = math.sqrt
>>> callable(x)
False
>>> callable(y)
True
知識點二
如果在函數的開頭寫下字符串,它就會作為函數的一部分進行存儲,這稱為文檔字符串。
def say_hello(name):
? ? 'print hello + name'
? ? print 'hello,' + name
文檔字符串可以按如下方式訪問:
>>> say_hello.__doc__
'print hello + name'
注意:__doc__是函數屬性
知識點三
*(1,2,3) 等價于 1,2,3
**{'x':1,'y':2,'z':3} 等價于 x=1,y=2,z=3
知識點四
變量和所對應的值用的是個“不可見”的字典,內建的vars函數可以返回這個字典:
>>> x = 1
>>> scope = vars()
>>> scope['x']
1
>>> scope['x'] += 1
>>> x
2
globals函數獲取全局變量值,該函數的近親是vars,它可以返回全局變量的字典(locals返回局部變量的字典)。例如:在局部變量有parameter,想要調用全局變量parameter,此時就要使用globals()['parameter']來獲取。
如果在函數內使用全局變量,必須先聲明這是全局變量,再來使用,例如
>>> x = 1
>>>def add_global_x():
? ? ? ? ? ? ?global x
? ? ? ? ? ? ?x = x +1
>>> x
2
知識點五
默認參數很有用,但使用不當,也會掉坑里。默認參數有個最大的坑,演示如下:
先定義一個函數,傳入一個list,添加一個END再返回:
def add_end(L=[]):
? ? ? ? ? ? ? ?L.append('END')
? ? ? ? ? ? ? return L
當你正常調用時,結果似乎不錯:
>>>add_end([1, 2, 3])
[1, 2, 3, 'END']
>>>add_end(['x', 'y', 'z'])
['x', 'y', 'z', 'END']
當你使用默認參數調用時,一開始結果也是對的:
>>>add_end()['END']
但是,再次調用add_end()時,結果就不對了:
>>>add_end()['END', 'END']
>>>add_end()['END', 'END', 'END']
很多初學者很疑惑,默認參數是[],但是函數似乎每次都“記住了”上次添加了'END'后的list。
原因解釋如下:
Python函數在定義的時候,默認參數L的值就被計算出來了,即[],因為默認參數L也是一個變量,它指向對象[],每次調用該函數,如果改變了L的內容,則下次調用時,默認參數的內容就變了,不再是函數定義時的[]了。
所以,定義默認參數要牢記一點:默認參數必須指向不變對象!
要修改上面的例子,我們可以用None這個不變對象來實現:
def add_end(L=None):
? ? ? ? ? ? ? ? ?if L is None:?
? ? ? ? ? ? ? ? ? ? ? ? ? L = []? ??
? ? ? ? ? ? ? ? ? L.append('END')
? ? ? ? ? ? ? ? ? returnL
現在,無論調用多少次,都不會有問題:
>>>add_end()['END']
>>>add_end()['END']
為什么要設計str、None這樣的不變對象呢?因為不變對象一旦創建,對象內部的數據就不能修改,這樣就減少了由于修改數據導致的錯誤。此外,由于對象不變,多任務環境下同時讀取對象不需要加鎖,同時讀一點問題都沒有。我們在編寫程序時,如果可以設計一個不變對象,那就盡量設計成不變對象。