天天看點

初學Python——函數

一、函數定義

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)位置參數

初學Python——函數
初學Python——函數
def func(names):
    print(names)
    names[1] = 'jujinyi'
 
names = ['aaron','jim']
func(names)
print(names)

#輸出:
['aaron', 'jim']
['aaron', 'jujinyi']      

View Code

永久性改變了清單的值。如果想要對清單附件操作,可以用切片的方式

初學Python——函數
初學Python——函數
def func(names):
    print(names)
    names[1] = 'jujinyi'
 
names = ['aaron','jim']
func(names)
print(names)

#輸出:
['aaron', 'jim']
['aaron', 'jim']      

(2)關鍵參數

本質上和位置參數是一樣的,沒有什麼差別

(3)元組傳遞

将傳進去的元組使用list函數

初學Python——函數
初學Python——函數
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.遞歸的效率不高,遞歸層次過多容易導緻棧溢出