python基礎——第6章 抽象
6.3 自定義函式
# 斐波那契數函式
def fibs(num):
result = [0, 1]
for i in range(num-2):
result.append(result[-2] + result[-1])
return result
6.3.1 給函式編寫文件
文件字串(docstring)
下面的程式碼演示瞭如何給函式新增文
檔字串:
def square(x):
'Calculates the square of the number x.'
return x * x
可以像下面這樣訪問文件字串:
>>> square.__doc__
'Calculates the square of the number x.'
注意 __doc__是函式的一個屬性。屬性將在第7章詳細介紹。屬性名中的雙下劃線表示這是一個特殊的屬性。特殊(“魔法”)屬性將在第9章討論。
6.4 引數魔法
注意 引數儲存在區域性作用域內。
6.4.3 關鍵字引數和預設值
關鍵字引數最大的優點在於,可以指定預設值。
6.4.4 收集引數
允許提供任意數量的引數
def print_paras(*argv):
print(argvS)
- 引數前面的星號將所有實參都放在一個元組中,它收集的是列表而不是元組中多餘的值。
- 星號收集餘下的位置引數。如果沒有可供收集的引數,params將是一個空元組。
- 帶星號的引數也可放在其他位置,在這種情況下:需要使用名稱來指定都需引數。
- 星號不會收集關鍵字引數。
>>> def in_the_middle(x, *y, z):
... print(x, y, z)
...
>>> in_the_middle(1, 2, 3, 4, 5, z=7)
1 (2, 3, 4, 5) 7
>>> in_the_middle(1, 2, 3, 4, 5, 7)
Traceback (most recent call last) :
File "<stdin>", line 1, in <module>
TypeError: in_the_middle() missing 1 required keyword-only argument: 'z'
- 星號不會收集關鍵字引數。
>>> print_params_2('Hmm...', something=42)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: print_params_2() got an unexpected keyword argument 'something'
- 要收集關鍵字引數,可使用兩個星號。
>>> def print_params_3(**params):
... print(params)
...
>>> print_params_3(x=1, y=2, z=3)
{'z': 3, 'x': 1, 'y': 2}
這樣得到的是一個字典而不是元組。可結合使用這些技術。
6.4.5 分配引數
同樣用(’* ‘和’ '),通過在呼叫函式時使用運算子實現。這種做法也可用於引數列表的一部分,條件是這部分位於引數列表末尾。通過使用運算子 **,可將字典中的值分配給關鍵字引數。
如果在定義和呼叫函式時都使用或,將只傳遞元組或字典。還不如不使用它們,還可省卻些麻煩。
>>> def with_stars(**kwds):
... print(kwds['name'], 'is', kwds['age'], 'years old')
...
>>> def without_stars(kwds):
... print(kwds['name'], 'is', kwds['age'], 'years old')
...
>>> args = {'name': 'Mr. Gumby', 'age': 42}
>>> with_stars(**args)
Mr. Gumby is 42 years old
>>> without_stars(args)
Mr. Gumby is 42 years old
對於函式with_stars,在定義和呼叫它時都使用了星號,而對於函式without_stars,我在定義和呼叫它時都沒有使用,但這兩種做法的效果相同。因此,只有在定義函式(允許可變數量的引數)或呼叫函式(拆分字典或序列)時使用,星號才能發揮作用。
6.5 作用域
名稱空間或作用域
- 全域性作用域
- 每個函式呼叫都將建立一個
作用域巢狀(閉包)
python函式可以巢狀,即可將一個函式放在另一個函式內,巢狀通常用處不大,但有一個很突出的用途:使用一個函式來建立另一個函式。
def multiplier(factor):
def multiplyByFactor(number):
return number * factor
return multiplyByFactor
在這裡,一個函式位於另一個函式中,且外面的函式返回裡面的函式。也就是返回一個函式,而不是呼叫它。重要的是,返回的函式能夠訪問其定義所在的作用域。換而言之,它攜帶著自己所在的環境(和相關的區域性變數)!
每當外部函式被呼叫時,都將重新定義內部的函式,而變數factor的值也可能不同。由於Python的巢狀作用域,可在內部函式中訪問這個來自外部區域性作用域(multiplier)的變數,如下所示:
>>> double = multiplier(2)
>>> double(5)
10
>>> triple = multiplier(3)
>>> triple(3)
9
>>> multiplier(5)(4)
20
像multiplyByFactor這樣儲存其所在作用域的函式稱為閉包。
通常,不能給外部作用域內的變數賦值,但如果一定要這樣做,可使用關鍵字nonlocal。這個關鍵字的用法與global很像,讓你能夠給外部作用域(非全域性作用域)內的變數賦值。
6.6 遞迴
- 基線條件(針對最小的問題):滿足這種條件時函式將直接返回一個值。
- 遞迴條件:包含一個或多個呼叫,這些呼叫旨在解決問題的一部分。
map、filter、reduce
Python提供了一些有助於進行這種函數語言程式設計的函式:map、filter和reduce。在較新的Python版本中,函式map和filter的用途並不大,應該使用列表推導來替代它們。你可使用map將序列的所有元素傳遞給函式。
>>> list(map(str, range(10))) # 與[str(i) for i in range(10)]等價
['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
你可使用filter根據布林函式的返回值來對元素進行過濾。
>>> def func(x):
... return x.isalnum()
...
>>> seq = ["foo", "x41", "?!", "***"]
>>> list(filter(func, seq))
['foo', 'x41']
6.7 本章介紹的新函式
函 數 | 描 述 |
---|---|
help(functionName) | 獲取名為functionName函式的資訊 |
callable(x) | 判斷物件x是否可呼叫 |
map(func, seq[, seq, …]) | 對序列中的所有元素執行函式 |
filter(func, seq) | 返回一個列表,其中包含對其執行函式時結果為真的所有元素 |
reduce(func, seq[, initial]) | 等價於 func(func(func(seq[0], seq[1]), seq[2]), …) |
sum(seq) | 返回 seq 中所有元素的和 |
apply(func[, args[, kwargs]]) | 呼叫函式(還提供要傳遞給函式的引數) |
globals() | 返回一個包含全域性變數的字典,類似於vars,globals()[‘parameter’]來訪問名為parameter的全域性變數 |
locals() | 返回一個包含區域性變數的字典 |