一、函數定義
1 def name( parameters): #沒有參數括号内可以為空
2 "函數描述" #其實就是注釋
3 <代碼塊>
4 return [expression] #沒有傳回值可以不加[]内容,也可以省略return
def是定義函數的關鍵字,name是函數名,parameters是形參
函數描述可以省略,但建議要有
expression是傳回值,可以沒有傳回值,也可以沒有retrun。
函數在return處結束。
二、傳參過程
這裡需要了解幾個名詞:位置參數、關鍵參數、預設參數
1.位置參數:按照函數形式參數的順序傳遞參數
def func(x,y):
print("x={0} y={1}".format(x,y))
func(3,4)
func(4,3)
#輸出:
x=3 y=4
x=4 y=3
可以發現,位置參數的使用相當于C語言當中的函數調用方式。
2.關鍵參數:指的是在傳遞參數時,不必考慮形式參數的具體先後順序,以“形式參數=實際參數”的形式傳參。
def func(x,y):
print("x={0} y={1}".format(x,y))
func(y=3,x=4)
#輸出結果:
x=4 y=3
3.預設參數:如果函數有預設參數,允許調用函數時不對預設參數傳參(這時形參為預設值)
def text2(x,y=2):#y為預設參數,非必須傳遞
print(x,y)
text2(1) #可以這樣調用
text2(1,3) #也可以這樣調用
#輸出結果:
1 2
1 3
4.參數組
如何向函數傳遞一個元組呢?
需要參數組。
def text3(*args):
print(args)
text3(1,2,3) #當使用參數組時,調用函數可以不傳參
#輸出:
(1,2,3)
形參中*args是參數組,可以接收數量不固定的參數,也可以接收0個參數,并将這些參數組成一個元組在函數中使用。
參數組可以在參數個數不确定的情況下使用。
5.字典的傳遞
def text5(**kwargs):#向函數傳遞字典
print(kwargs)
text5() #調用函數時可以不傳參
text5(name="liuwei",sex="man",index=3) #标準的傳參傳字典過程
#輸出結果:
{“name”:"liuwei","sex":"man","index":3} #3是int型
這種傳參方式很容易和關鍵參數混淆。
6.多種類型參數傳遞和優先級問題
def text6(a,b=2,*args,**kwargs):
print(a)
print(b)
print(args)
print(kwargs)
text6("woo",3,sex="m",hobby="aa")
#輸出結果:
woo
3
()
{'sex': 'm', 'hobby': 'aa'}
在定義函數時,形參應當遵循 普通參數-->預設參數-->參數組-->字典參數 的順序
在調用函數時,實參應當遵循 位置參數-->關鍵參數-->參數組-->字典參數 的順序
這樣做為的是避免混淆。
7.如何傳遞清單
(1)位置參數
def func(names):
print(names)
names[1] = 'jujinyi'
names = ['aaron','jim']
func(names)
print(names)
#輸出:
['aaron', 'jim']
['aaron', 'jujinyi']
View Code
永久性改變了清單的值。如果想要對清單附件操作,可以用切片的方式
def func(names):
print(names)
names[1] = 'jujinyi'
names = ['aaron','jim']
func(names)
print(names)
#輸出:
['aaron', 'jim']
['aaron', 'jim']
(2)關鍵參數
本質上和位置參數是一樣的,沒有什麼差別
(3)元組傳遞
将傳進去的元組使用list函數
def func(*toppings):
toppings = list(toppings)
print(toppings)
func('mushrooms','extra','cheese')
func('mushrooms','extra')
#輸出:
['mushrooms', 'extra', 'cheese']
['mushrooms', 'extra']
三、傳回值
可以傳回任何類型。基本資料類型(字元、整型等),清單(元組),字典,集合,甚至函數名也可以被傳回
如果傳回多個值,所有的傳回值會被封裝成一個元組傳回
四、局部變量和全局變量
1.定義
全局變量是定義在函數體外面的變量,局部變量是定義在函數體内的變量
全局變量的作用域和生命周期從被定義開始直到程式結束,而局部變量則是從被定義到所在的函數結束。
2.全局變量的使用
全局變量當然可以在函數體外随意使用,在函數體内還會一樣嗎?
a=6
c=[1,2,3,4,5]
def text():
a=5
b=10
c[1]=0
print("a={0},b={1},c={2}".format(a,b,c))
text()
print("a={0},b={1},c={2}".format(a,b,c))
運作結果報錯,問題出在最後一行:NameError: name 'b' is not defined。因為變量b是局部變量,隻存在于函數内,在函數外已經不存在了。
改一下:
print("a={0},c={1}".format(a,c))
#輸出結果:
a=5,b=10,c=[1, 0, 3, 4, 5]
a=6,c=[1, 0, 3, 4, 5]
發現了什麼問題?a和c同為全局變量,都在函數内經過了修改,但是c被永久性的修改,a隻是在函數内被修改,出來後被複原了。
這是因為清單c在函數内外都是原件,而整型a在函數内修改,修改的是函數拷貝的臨時變量,保證了全局變量的安全性。
是以,可以用函數直接對清單、字典、集合等複雜類型的全局變量進行操作,但是無法在函數内對基本類型(如int,str,float等)的全局變量進行修改。
3.如何在函數内修改基本類型的全局變量?
Python提供了global關鍵字來進行聲明
a=6
def text():
global a #聲明要在函數内修改全局變量
a=10
print(a)
text()
print(a)
#運作結果:
10
10
這樣,全局變量就被修改了。
雖然有這種方法,但是如果沒有這種強烈需求的話,盡量不要這麼做。
五、高階函數和嵌套函數
1.以下兩個條件滿足其一就可稱之為高階函數:
(1)把函數名當做實參傳遞給另一個函數
(2)傳回值中包含函數名
2.函數可以嵌套,即函數體内可以定義函數
六、遞歸
定義:如果在函數内部可以調用自己,那麼就稱之為遞歸函數
遞歸需要滿足的特性:
1.必須有一個明确的結束條件 (python内有預定的最大遞歸層數:999,程式的保護機制)
2.每深入一層時,問題的規模應該減小
3.遞歸的效率不高,遞歸層次過多容易導緻棧溢出