Python中的函數和作用域
1. 函數
1.1 函數的簡介
當我們在重複使用某一功能時,我們可能會寫很多重複的代碼,例如我們求圓的周長,當圓的直徑改變時,是不是我們又要重新寫一遍計算過程呢?如果涉及到很複雜的過程,而下次使用僅僅改變參數,那麼我們還有必要重複這一過程嗎?
這時我們可以利用函數來解決這一問題。一個功能就像黑盒一樣,我們不需要知道它是怎麼工作的,我們只要知道接口(輸入,輸出)即可使用。
例如Python
的內置函數print
我們只要知道它需要我們提供哪些參數,以及它會給我們怎樣的輸出即可。這就是所謂的抽象
,我們不知道工作原理,但也能使用它。所以我們可以寫一個函數(黑盒),設置直徑爲輸入,周長爲輸出,當函數寫好後,我們只要輸入直徑即可,不用考慮函數內部是如何計算的,我們得到輸出後,繼續做我們想做的事情。
當我們想做一道菜時,有人負責洗菜,有人切菜,有人炒菜,將這些人的工作合在一起,就完成了做菜這個任務,這就是分解
的思想,我們將這個任務看成是函數,許多函數在一起完成了一件比較大的事情。
可以簡單理解一塊可重複使用的代碼,我們稱之爲函數(function)
,當我們調用函數時,這個函數纔會執行。
1.2 函數的特徵
- 名稱
- 參數 (0 或 多個)
- 有docstring (可選,但是建議有,註釋的意思)
- 函數體
- 返回一些值
以下是定義一個函數簡單的例子,注意函數內要有四個空格的縮進,如果沒有返回值的話,會默認返回None
:
#def是用來定義函數的關鍵字
#is_even是函數的名稱
#i是參數(參數可以是任何類型)
#三個引號括起來的是docstring
#docstring下面的語句是函數體
#return後的是返回值
def is_even( i ):
"""
Input: i是一個正的int類型
Returns True 如果 i 是偶數, 否則返回 False
"""
print("inside is_even")
return i%2 == 0
#調用函數,並用a接收返回值
a = is_even(2)
print(a)
2. 作用域
2.1 形參和實參
首先我們先不涉及編程。高中的函數y = f(x)
,這個x就相當於是形參,指一種抽象,將我們用f(3)
的時候,這個3
就是實參了,就是實際我們使用的值,形參和實參大致就是這個意思,不要搞混了。例如:
def f( x ):#x是形參
x = x + 1
print('in f(x): x =', x)
return x
#以下是調用函數
x = 3#初始化x
z = f( x )#調用函數,傳入實參,將返回值給z
2.2 函數作用域
利用pythontutor
網站對代碼的執行進行可視化,我把所有步驟都截了下來,先看圖,右側反映了變量的變化情況。
可以看到函數內是一個作用域,外面是訪問不到的(一般情況)。當進入一個函數時,一個新的作用域就被創建了。函數內的x
和外面的x
不是一個x
,x
是不可變量,這和之後的list
等數據類型不一樣,之後再說。
- 函數裏可以訪問外面的變量
- 函數裏不可以修改外部定義的變量
以下是是幾個例子,如果有不清楚,可以進入 www.pythontutor.com(我推薦的代碼可視化網站)中嘗試運行。
第一個例子,在外邊定義了一個x
,但是在f內又定義了一個x
,這兩個x
不是一個x
,函數內部使用的x
是函數內部定義的。
def f(y):
x = 1
x += 1
print(x)
x = 5
f(x)
print(x)
第二個例子,在g
中使用的x
是外部定義的x
def g(y):
print(x)
print(x + 1)
x = 5
g(x)
print(x)
第三個例子,會報錯,不能在內部修改外部的值,UnboundLocalError: local variable 'x' referenced before assignment
def h(y):
x += 1
x = 5
h(x)
print(x)
3. 參考
參考了Mit 6.0001的課件