【廖雪峰python入門筆記】函式
1. 函式
我們知道圓的面積計算公式為:
S = πr²
當我們知道半徑r的值時,就可以根據公式計算出面積。假設我們需要計算3個不同大小的圓的面積:
r1 = 12.34
r2 = 9.08
r3 = 73.1
s1 = 3.14 * r1 * r1
s2 = 3.14 * r2 * r2
s3 = 3.14 * r3 * r3
當程式碼出現有規律的重複的時候,你就需要當心了,每次寫3.14 * x * x不僅很麻煩,而且,如果要把3.14改成3.14159265359的時候,得全部替換。
有了函式,我們就不再每次寫s = 3.14 * x * x,而是寫成更有意義的函式呼叫 s = area_of_circle(x),而函式 area_of_circle 本身只需要寫一次,就可以多次呼叫。
抽象
是數學中非常常見的概念。舉個例子:
計算數列的和,比如:1 + 2 + 3 + … + 100,寫起來十分不方便,於是數學家發明了求和符號∑,可以把1 + 2 + 3 + … + 100記作:
100
∑n
n=1
這種抽象記法非常強大,因為我們看到∑就可以理解成求和,而不是還原成低階的加法運算。
而且,這種抽象記法是可擴充套件的,比如:
100
∑(n²+1)
n=1
還原成加法運算就變成了:
(1 x 1 + 1) + (2 x 2 + 1) + (3 x 3 + 1) + … + (100 x 100 + 1)
可見,藉助抽象
,我們才能不關心底層的具體計算過程,而直接在更高的層次上思考問題。
寫計算機程式也是一樣,函式就是最基本的一種程式碼抽象
的方式。
Python不但能非常靈活地定義函式,而且本身內建了很多有用的函式,可以直接呼叫。
2. 函式呼叫
Python內建了很多有用的函式,我們可以直接呼叫。
要呼叫一個函式,需要知道函式的名稱
和引數
,比如求絕對值
的函式 abs
,它接收一個引數。
可以直接從Python的官方網站檢視文件
:
http://docs.python.org/2/library/functions.html#abs
也可以在互動式命令列通過 help(abs)
檢視abs函式的幫助資訊。
呼叫 abs
函式:
>>> abs(100)
100
>>> abs(-20)
20
>>> abs(12.34)
12.34
呼叫函式的時候,如果傳入的引數數量
不對,會報TypeError
的錯誤,並且Python會明確地告訴你:abs()有且僅有1個引數,但給出了兩個:
>>> abs(1, 2)
TypeError: abs() takes exactly one argument (2 given)
如果傳入的引數數量是對的,但引數型別
不能被函式所接受,也會報TypeError
的錯誤,並且給出錯誤資訊:str是錯誤的引數型別:
>>> abs('a')
TypeError: bad operand type for abs(): 'str'
而比較函式 cmp(x, y)
就需要兩個引數,如果 x<y
,返回-1
,如果 x==y
,返回 0
,如果 x>y
,返回 1
:
>>> cmp(1, 2)
-1
>>> cmp(2, 1)
1
>>> cmp(3, 3)
0
Python內建的常用函式還包括資料型別轉換
函式,比如 int()函式
可以把其他資料型別轉換為整數:
>>> int('123')
123
>>> int(12.34)
12
str()函式
把其他型別轉換成 str:
>>> str(123)
'123'
>>> str(1.23)
'1.23'
3. 編寫函式
在Python中,定義一個函式要使用 def
語句,依次寫出函式名
、括號
、括號中的引數
和冒號:
,然後,在縮排塊中編寫函式體,函式的返回值
用 return
語句返回。
我們以自定義一個求絕對值的 my_abs 函式為例:
def my_abs(x):
if x >= 0:
return x
else:
return -x
請注意,函式體內部的語句在執行時,一旦執行到return
時,函式就執行完畢
,並將結果
返回。因此,函式內部通過條件判斷和迴圈可以實現非常複雜的邏輯。
如果沒有return
語句,函式執行完畢後也會返回結果,只是結果為 None。
return None
可以簡寫為return。
4. 返回多值
函式可以返回多個值嗎?答案是肯定的。
比如在遊戲中經常需要從一個點移動到另一個點,給出座標、位移和角度,就可以計算出新的座標:
math包
提供了sin()
和cos()
函式,我們先用import引用它:
import math
def move(x, y, step, angle):
nx = x + step * math.cos(angle)
ny = y - step * math.sin(angle)
return nx, ny
這樣我們就可以同時獲得返回值:
>>> x, y = move(100, 100, 60, math.pi / 6)
>>> print x, y
151.961524227 70.0
但其實這只是一種假象,Python函式返回的仍然是單一值:
>>> r = move(100, 100, 60, math.pi / 6)
>>> print r
(151.96152422706632, 70.0)
用print列印返回結果,原來返回值是一個tuple!
但是,在語法
上,返回一個tuple可以省略括號
,而多個變數可以同時接收
一個tuple,按位置
賦給對應的值,所以,Python的函式返回多值
其實就是返回一個tuple
,但寫起來更方便。
5. 遞迴函式
在函式內部,可以呼叫其他函式。如果一個函式在內部呼叫自身本身,這個函式就是遞迴函式
。
舉個例子,我們來計算階乘 n! = 1 * 2 * 3 * … * n,用函式 fact(n)表示,可以看出:
fact(n) = n! = 1 * 2 * 3 * ... * (n-1) * n = (n-1)! * n = fact(n-1) * n
所以,fact(n)可以表示為 n * fact(n-1),只有n=1時需要特殊處理。
於是,fact(n)用遞迴的方式寫出來就是:
def fact(n):
if n==1:
return 1
return n * fact(n - 1)
上面就是一個遞迴函式。可以試試:
>>> fact(1)
1
>>> fact(5)
120
>>> fact(100)
93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000L
如果我們計算fact(5),可以根據函式定義看到計算過程如下:
===> fact(5)
===> 5 * fact(4)
===> 5 * (4 * fact(3))
===> 5 * (4 * (3 * fact(2)))
===> 5 * (4 * (3 * (2 * fact(1))))
===> 5 * (4 * (3 * (2 * 1)))
===> 5 * (4 * (3 * 2))
===> 5 * (4 * 6)
===> 5 * 24
===> 120
遞迴函式的優點是定義簡單
,邏輯清晰
。理論上,所有的遞迴函式
都可以寫成迴圈
的方式,但迴圈的邏輯不如遞迴清晰。
使用遞迴函式需要注意防止棧溢位
。在計算機中,函式呼叫是通過棧(stack)
這種資料結構實現的,每當進入一個函式呼叫
,棧就會加一層棧幀
,每當函式返回
,棧就會減一層棧幀
。由於棧的大小
不是無限的,所以,遞迴呼叫的次數過多,會導致棧溢位
。可以試試計算 fact(10000)。
例項
漢諾塔 (http://baike.baidu.com/view/191666.htm) 的移動也可以看做是遞迴函式。
我們對柱子編號為a, b, c,將所有圓盤從a移到c可以描述為:
如果a只有一個圓盤,可以直接移動到c;
如果a有N個圓盤,可以看成a有1個圓盤(底盤) + (N-1)個圓盤,首先需要把 (N-1) 個圓盤移動到 b,然後,將 a的最後一個圓盤移動到c,再將b的(N-1)個圓盤移動到c。
請編寫一個函式,給定輸入 n, a, b, c,列印出移動的步驟:
move(n, a, b, c)
例如,輸入 move(2, ‘A’, ‘B’, ‘C’),列印出:
A –> B
A –> C
B –> C
函式 move(n, a, b, c) 的定義是將 n 個圓盤從 a 藉助 b 移動到 c。
def move(n, a, b, c):
if n ==1:
print a, '-->', c
return
move(n-1, a, c, b)
print a, '-->', c
move(n-1, b, a, c)
move(4, 'A', 'B', 'C')
6. 預設引數
定義函式的時候,還可以有預設引數
。
例如Python自帶的 int() 函式
,其實就有兩個引數,我們既可以傳一個引數,又可以傳兩個引數:
>>> int('123')
123
>>> int('123', 8)
83
int()函式的第二個引數是轉換進位制
,如果不傳,預設
是十進位制 (base=10),如果傳了,就用傳入的引數。
可見,函式的預設引數的作用是簡化呼叫
,你只需要把必須的引數傳進去。但是在需要的時候,又可以傳入額外的引數來覆蓋預設引數值。
我們來定義一個計算 x 的N次方的函式:
def power(x, n):
s = 1
while n > 0:
n = n - 1
s = s * x
return s
假設計算平方的次數最多,我們就可以把 n 的預設值設定為 2:
def power(x, n=2):
s = 1
while n > 0:
n = n - 1
s = s * x
return s
這樣一來,計算平方就不需要傳入兩個引數了:
>>> power(5)
25
由於函式的引數按從左到右的順序匹配
,所以預設引數只能
定義在必需引數的後面:
# OK:
def fn1(a, b=1, c=2):
pass
# Error:
def fn2(a=1, b):
pass
7. 可變引數
如果想讓一個函式能接受任意個
引數,我們就可以定義一個可變引數:
def fn(*args):
print args
可變引數的名字前面有個*
號,我們可以傳入0個、1個或多個引數給可變引數:
>>> fn()
()
>>> fn('a')
('a',)
>>> fn('a', 'b')
('a', 'b')
>>> fn('a', 'b', 'c')
('a', 'b', 'c')
可變引數也不是很神祕,Python直譯器會把傳入的一組引數
組裝成一個tuple
傳遞給可變引數
,因此,在函式內部,直接把變數 args 看成一個 tuple
就好了。
定義可變引數的目的也是為了簡化呼叫
。假設我們要計算任意個數的平均值,就可以定義一個可變引數:
def average(*args):
sum = 0.0
if len(args) == 0:
return sum
for x in args:
sum = sum + x
return sum / len(args)
這樣,在呼叫的時候,可以這樣寫:
>>> average()
0
>>> average(1, 2)
1.5
>>> average(1, 2, 2, 3, 4)
2.4
相關文章
- 【廖雪峰python入門筆記】列表生成式Python筆記
- 【廖雪峰python入門筆記】dictPython筆記
- 【廖雪峰python入門筆記】setPython筆記
- 【廖雪峰python入門筆記】切片Python筆記
- 【廖雪峰python入門筆記】迭代Python筆記
- 【廖雪峰python入門筆記】變數Python筆記變數
- 【廖雪峰python入門筆記】if語句Python筆記
- 【廖雪峰python入門筆記】for迴圈Python筆記
- 【廖雪峰python入門筆記】list_建立Python筆記
- 【廖雪峰python入門筆記】tuple_建立Python筆記
- 【廖雪峰python入門筆記】while迴圈Python筆記While
- 【廖雪峰python入門筆記】多重迴圈Python筆記
- 【廖雪峰python入門筆記】break和continuePython筆記
- 【廖雪峰python入門筆記】list刪除元素_pop()Python筆記
- 【廖雪峰python入門筆記】list_替換元素Python筆記
- 【廖雪峰python入門筆記】tuple_“元素可變”Python筆記
- 【廖雪峰python入門筆記】tuple_建立單元素Python筆記
- 【廖雪峰python入門筆記】字串_轉義字元的使用Python筆記字串字元
- 【廖雪峰python入門筆記】raw 字串和多行字串表示Python筆記字串
- 【廖雪峰python入門筆記】整數和浮點數Python筆記
- 【廖雪峰python入門筆記】list_按照索引訪問Python筆記索引
- 【廖雪峰python入門筆記】list_倒序訪問Python筆記
- 【廖雪峰python入門筆記】布林運算和短路計算Python筆記
- 【廖雪峰python入門筆記】list新增元素_append()和insert()Python筆記APP
- 【廖雪峰python進階筆記】模組Python筆記
- 廖雪峰Git教程筆記Git筆記
- 【廖雪峰python入門筆記】Unicode編碼_UnicodeDecodeError處理Python筆記UnicodeError
- 【廖雪峰python進階筆記】函數語言程式設計Python筆記函數程式設計
- 【廖雪峰python進階筆記】定製類Python筆記
- 【廖雪峰python進階筆記】類的繼承Python筆記繼承
- 廖雪峰JS學習總結-函式篇JS函式
- 廖雪峰JS學習總結-入門篇JS
- 【廖雪峰python進階筆記】物件導向程式設計Python筆記物件程式設計
- 廖雪峰Git學習筆記1-Git簡介Git筆記
- 跟著廖雪峰學python 005Python
- Python廖雪峰13個案例講解分析帶你全面入門人工智慧Python人工智慧
- 廖雪峰《Python3 基礎教程》讀書筆記——第一、第二章Python筆記
- Python入門-函式Python函式