【python?5】函數 --學習筆記

什么是函數

我們知道圓的面積計算公式為:

S = πr2

當我們知道半徑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 本身只需要寫一次,就可以多次調用。


調用函數

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)

Traceback (most recent call last):

File "", line 1, in

TypeError: abs() takes exactly one argument (2 given)

如果傳入的參數數量是對的,但參數類型不能被函數所接受,也會報TypeError的錯誤,并且給出錯誤信息:str是錯誤的參數類型:

>>> abs('a')

Traceback (most recent call last):

File "", line 1, in

TypeError: bad operand type for abs(): 'str'

而比較函數cmp(x, y)就需要兩個參數,如果x<y,返回-1,如果x==y,返回0,如果x>y,返回1

>>> cmp(1, 2)【cmp注意點:python3無法直接運行得出結果】

-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'

任務:

sum()函數接受一個list作為參數,并返回list所有元素之和。請計算 1*1 + 2*2 + 3*3 + ... + 100*100。

代碼如下:

方法一

方法二
方法三


編寫函數

在Python中,定義一個函數要使用def語句,依次寫出函數名、括號、括號中的參數和冒號:,然后,在縮進塊中編寫函數體,函數的返回值用return語句返回。

我們以自定義一個求絕對值的 my_abs 函數為例:

def my_abs(x):

? ?if x >= 0:

? ? ? ?return x

? ?else:

? ? ? ?return -x

請注意,函數體內部的語句在執行時,一旦執行到return時,函數就執行完畢,并將結果返回。因此,函數內部通過條件判斷和循環可以實現非常復雜的邏輯。

如果沒有return語句,函數執行完畢后也會返回結果,只是結果為 None。

return None可以簡寫為return。

任務:

請定義一個 square_of_sum 函數,它接受一個list,返回list中每個元素平方的和。

參考代碼:

方法一
方法二

返回多值

函數可以返回多個值嗎?答案是肯定的。

比如在游戲中經常需要從一個點移動到另一個點,給出坐標、位移和角度,就可以計算出新的坐標:

# 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)

>>>printx,y

151.961524227 70.0

但其實這只是一種假象,Python函數返回的仍然是單一值:

>>>r=move(100,100,60,math.pi/6)

>>>printr

(151.96152422706632, 70.0)

用print打印返回結果,原來返回值是一個tuple!

但是,在語法上,返回一個tuple可以省略括號,而多個變量可以同時接收一個tuple,按位置賦給對應的值,所以,Python的函數返回多值其實就是返回一個tuple,但寫起來更方便。

一元二次方程的定義是:ax2 + bx + c = 0

請編寫一個函數,返回一元二次方程的兩個解。

參考代碼:

import math

def quadratic_equation(a, b, c):

? ?x=math.sqrt(b*b-4*a*c)

? ?return (-b+x)/(2*a),(-b-x)/(2*a)

print quadratic_equation(2, 3, 0)

print quadratic_equation(1, -6, 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

方法一
方法二

定義默認參數

定義函數的時候,還可以有默認參數。

例如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

任務:

請定義一個 greet() 函數,它包含一個默認參數,如果沒有傳入,打印 'Hello, world.',如果傳入,打印 'Hello, xxx.'

方法一
方法二

定義可變參數

如果想讓一個函數能接受任意個參數,我們就可以定義一個可變參數:

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):...

這樣,在調用的時候,可以這樣寫:

>>> average()

0

>>> average(1, 2)

1.5

>>> average(1, 2, 2, 3, 4)

2.4

任務:

請編寫接受可變參數的 average() 函數。

方法一
方法二
方法三
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,606評論 6 533
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,582評論 3 418
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 176,540評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,028評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,801評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,223評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,294評論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,442評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,976評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,800評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,996評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,543評論 5 360
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,233評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,662評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,926評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,702評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,991評論 2 374

推薦閱讀更多精彩內容