1. 程式人生 > >python基礎——第6章 抽象

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() 返回一個包含區域性變數的字典