函數
函數是組織好的,可重復使用的,用來實現單一,或相關聯功能的代碼段。
函數能提高應用的模塊性,和代碼的重復利用率。你已經知道Python提供了許多內建函數,比如print()。但你也可以自己創建函數,這被叫做用戶自定義函數。
一、定義函數
1、定義一個由自己想要功能的函數,以下是簡單的規則:
- 函數代碼塊以 def 關鍵詞開頭,后接函數標識符名稱和圓括號 ()。
- 任何傳入參數和自變量必須放在圓括號中間,圓括號之間可以用於定義參數。
- 函數的第一行語句可以選擇性地使用文檔字符串—用於存放函數說明。
- 函數內容以冒號起始,並且縮進。
- return [表達式] 結束函數,選擇性地返回一個值給調用方。不帶表達式的return相當於返回 None。
def test(): """ for test """ print("in the test funcation") return 0 # def 定義函數的關鍵字 # test 函數名(函數標識名稱符) # () 任何傳入參數和自變量必須放在圓括號中間,圓括號之間可以用於定義參數 # """for test""" 函數說明,說明函數作用,方便他人閱讀代碼 # print("in the test funcation") 函數體(代碼塊),注意縮進 # return 結束函數,選擇性地返回一個值給調用方。不帶表達式的return相當於返回 None
2、函數特征:
- 代碼重復利用
- 可擴展性
- 保持一致性
優化前:

#打印字符串 print("ABCD") print("EFGH") #現在下面有2個函數,每個函數處理完了,都需要使用上面的邏輯,那么唯一的方法就是拷貝2次這樣的邏輯 def test_1(): "test" print("in the test1") print("ABCD") print("EFGH") def test_2(): "test" print("in the test2") print("ABCD") print("EFGH")
優化后:

# 新定義一個函數 def test(): """test""" print("ABCD") print("EFGH") #在想執行打印字符串功能的函數中,調用test()函數就可以了 def test_1(): """test""" print("in the test1") test()# 調用test()函數 def test_2(): """test""" print("in the test2") test()# 調用test()函數
二、有參函數和無參函數:
1、無參函數實現和調用:

# 定位test() 無參函數 def test(): print("in the test") test() #調用函數 # in the test
2、有參函數實現和調用:
下面說說帶參數的函數:
- 形參:指的是形式參數,是虛擬的,不占用內存空間,形參單元只有被調用的時才分配內存單元
- 實參:指的是實際參數,是一個變量,占用內存空間,數據傳遞單向,實參傳給形參,形參不能傳給實參
def test(x,y): #x,y是形參 print(x) print(y) test(1,2) #1和2是實參 #輸出 1 2
(1)、位置參數
從上面的例子可以看出,實際參數和形式參數是一一對應的,如果調換位置,x和y被調用的時,位置也會互換,代碼如下:
def test(x,y): print(x) print(y) print("--------互換前-----") test(1,2) print("--------互換后-----") test(2,1) #輸出 --------互換前----- 1 2 --------互換后----- 2 1
因為定義x,y兩個形參,所以傳遞實參的時候,也只能傳遞兩個實參,多一個或少一個都是有問題的:
a:多傳遞一個參數

def test(x,y): print(x) print(y) print("--------多一個參數----") test(1,2,3) #輸出 --------多一個參數---- Traceback (most recent call last): File "D:/PycharmProjects/pyhomework/day3/函數_帶參數.py", line 8, in <module> test(1,2,3) TypeError: test() takes 2 positional arguments but 3 were given #test()函數需要傳兩個實參,你傳了三個實參
b:少傳遞一個實參

def test(x,y): print(x) print(y) print("--------少一個參數----") test(1) #輸出 --------少一個參數---- Traceback (most recent call last): File "D:/PycharmProjects/pyhomework/day3/函數_帶參數.py", line 8, in <module> test(1) TypeError: test() missing 1 required positional argument: 'y' #沒有給y參數傳實參
(2)、關鍵字參數
上面的位置參數,看起來有點死,必須形參和實參的位置一一對應,不然就會傳錯參數,為了避免這種問題,就有了關鍵字參數的玩法:關鍵字傳參不需要一一對應,只需要你指定你的哪個形參調用哪一個實參即可;
def test(x,y): print(x) print(y) print("--------互換前------") test(x=1,y=2) print("--------互換后------") test(y=2,x=1) #輸出 --------互換前------ 1 2 --------互換后------ 1 2
研究一下位置參數和關鍵字參數結合使用:
1,位置參數在前,關鍵字參數在后
def test(x,y): print(x) print(y) test(1,y=2) #輸出 1 2
def test(x,y,z): print(x) print(y) print(z) test(1,z=2,y=3) #輸出 1 3 2
2、上面的列子是關鍵字傳參傳給y,現在傳給x,代碼如下:
def test(x,y): print(x) print(y) test(1,x=2) #輸出 Traceback (most recent call last): File "D:/PycharmProjects/pyhomework/day3/函數_帶參數.py", line 8, in <module> test(1,x=2) TypeError: test() got multiple values for argument 'x' #給x形參傳的值過多,之前位置參數 就傳實參給x一次,后面關鍵字又傳實參給x,造成報錯
3 、關鍵字參數在前,位置參數在后:
def test(x,y): print(x) print(y) test(y=2,1) #輸出 File "D:/PycharmProjects/pyhomework/day3/函數_帶參數.py", line 8 test(y=2,1) ^ SyntaxError: positional argument follows keyword argument # 關鍵字參數在位置參數的前面
另外一種,就是關鍵字參數在中間:
def test(x,y,z): print(x) print(y) test(1,y=2,3) #輸出 File "D:/PycharmProjects/pyhomework/day3/函數_帶參數.py", line 8 test(1,y=2,3) ^ SyntaxError: positional argument follows keyword argument
結論:關鍵字參數是不能寫在位置參數前面的。
三、全局變量和局部變量
1、局部變量
局部變量:顧名思義,指在局部生效,定義在函數體內的變量只能在函數里面生效,出個這個函數體,就不能找到它,這個函數就是這個變量的作用域,如下代碼:
name = "apple" def test(name): print("before change:",name) name = "bananan" #局部變量name,只能在這個函數內生效,這個函數就是這個變量的作用域 print("after change:",name) test(name) print(name) #輸出 before change: apple after change: bananan #局部變量生效 bananan# 外部的變量還是apple,僅函數內的name變成了bananan
2、全局變量
全局變量:指的是在整個程序中都生效的變量,在整個代碼的頂層聲明:
name = "apple" def test(name): print("before change:",name) name = "bananan" #局部變量name,只能在這個函數內生效,這個函數就是這個變量的作用域 print("after change:",name) def test1(name): print(name) test(name) test(name1) print(name) #輸出 before change: apple after change: bananan #局部變量生效 apple# 全局變量 apple# 全局變量
注:全局變量的優先級是低於局部變量的,當函數體內沒有局部變量,才會去找全局變量
3、局部變量改成全局變量
- 改前用global先聲明一下全局變量
- 將全局變量重新賦值
name = "apple" def test(name): global name #使用global 聲明全局變量 print("before change:",name) name = "bananan" #全局變量重新賦值 print("after change:",name) def test1(name): print(name) test(name) test(name1) print(name) #輸出 before change: apple after change: bananan bananan bannann
注:最好不要用global這個關鍵字,因為你用了,其他人調你的函數時,就亂套了,而且還不好調試。
4、全局變量定義成列表
names = ['AAAA',"BBBB"] #定義一個列表 def test(): names[0] = "CCCC" print(names) print("--------test-----") test() print("------打印names--") print(names) #輸出 --------test----- ['CCCC', 'BBBB'] #函數內的names輸出 ------打印names-- ['CCCC', 'BBBB'] #函數外的names輸出
注:1、只有字符串和整數是不可以被修改的,如果修改,需要在函數里面聲明global。2、但是復雜的數據類型,像列表(list)、字典(dict)、集合(set)、類(class)都是可以修改的。
5、小實驗:
局部作用域和全局作用域的訪問順序
#局部作用域和全局作用域的訪問順序 x=0 def grandpa(): x=1 def dad(): x=2 def son(): x=3 print(x) son() dad() #調用grandpa grandpa() #輸出 3
注:作用域,只能是從里往外找,一層一層的的找。
全局變量和局部變量小結:
- 在子程序(函數)中定義的變量稱為局部變量,在程序一開始定義的變量稱為全局變量。
- 全局變量的作用域是整個程序,局部變量的作用域是定義該變量的子程序(函數)。
- 當全局變量和局部變量同名時:在定義局部變量的子程序內,局部變量起作用;在其他地方,全局變量起作用。