3-4 0基礎學Python(Python入門學習第三天),Python之什麼是函數,Python之 調用函數,Python中編寫函數,Python函數之返回多值Python之遞歸函數

Python之什麼是函數

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

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不但能非常靈活地定義函數,而且本身內置了很多有用的函數,可以直接調用。

Python之調用函數

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 "<stdin>", line 1, in <module>
TypeError: abs() takes exactly one argument (2 given)

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

>>> abs('a')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
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'

Python之編寫函數

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

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

def my_abs(x):
    if x >= 0:
        return x
    else:
        return -x

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

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

return None可以簡寫爲return。

Python函數之返回多值

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

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

# 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,但寫起來更方便。

Python之遞歸函數

在函數內部,可以調用其他函數。如果一個函數在內部調用自身本身,這個函數就是遞歸函數。

舉個例子,我們來計算階乘 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)。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章