1. 程式人生 > >python和函式的故事(預設引數,匿名函式)

python和函式的故事(預設引數,匿名函式)

預設引數
python為了簡化函式的呼叫,提供了預設的引數機制

製作一個函式,名為pow,傳入預設形參n=2,計算任意一個數的平方

def pow(x, n = 2):      #定義一個函式pow,傳入形參x,設定形參n=2,如果實參中沒有指定的話,那麼引數n就是用預設值2帶入式中
    r = 1                
    while n > 0:              
        r *= x        #即就是r=r*x
        n -= 1
    return r
pow(5)              #將實參5傳遞給形參x,沒有傳第二個實參得值,那麼形參n預設為為2
print(pow(5)) #輸出函式的值為25

在定義有預設引數的函式時,需要注意以下:

1,必選引數必須在前面,預設引數在後;
2,設定何種引數為預設引數?一般來說,將引數值變化小的設定為預設引數。

在python的內建函式中也存在著預設引數:

print(value, ..., sep=' ', end='\n', file=sys.stdout, flush=False)

2.不定長引數

有時可能需要一個函式能處理比當初宣告時更多的引數。這些引數叫做不定長引數(或者可變引數,不定的意思就是不確定函式使用者會傳遞多少個引數給形參,不定長引數包括*args和 **kwargs語法

*args 是可變的位置引數(positional arguments)列表,用來發送一個非鍵值對的可變數量的引數列表給一個函式
**kwargs 是可變的關鍵詞引數(keyword arguments)列表。
並且規定位置引數必須位於關鍵詞引數之前,即 *args 必須位於 **kwargs 之前。**kwargs用於將不定長度的鍵值對作為實參值傳遞給形參。

基本語法如下:

def  函式名(形參,*args):
    函式體
函式名(實參1,實參2.....)

加了星號(*)的變數args會存放所有非鍵值對的可變數量的引數列表,引數args資料型別為元組;

def
num(a,b,*args):
#設定形參a,b和不定長引數*args,其引數args可以自定義名稱,一般使用args表示 print ("a is", a) print ("b is", b) print ("args is", args) num(11,22,33,44,55,66) #將11傳遞給形參a,將12傳遞給形參b,將剩下的實參都傳給args引數中組成一個元組

輸出結果為:

a is 11
b is 22
args is (33, 44, 55, 66)

而加**的變數kwargs會存放不定長度的鍵值對作為實參值傳遞給形參。

def fun(a, b, *args, **kwargs):
    print ("a =", a)
    print ("b =", b)
    print ("args =", args)
    print ("kwargs: ")      
    for key, value in kwargs.items(): #對字典的鍵值進行遍歷
        print (key, "=", value)
fun(1, 2, 3, 4, 5, m=6, n=7, p=8)   #將實參1傳遞給形參a,實參2傳遞給形參b,將非鍵值對的值全部傳遞給不定長引數args,將鍵值對的值傳遞給不定長引數**kwargs

得到的結果為:

a = 1
b = 2
args = (3, 4, 5)
kwargs: 
m = 6
n = 7
p = 8

匿名函式
在Python,有兩種函式,一種是def定義的函式,需要設定函式名,一種是lambda函式(一種生成函式物件的表示式形式,不需要設定函式名,因為她和LISP語言很相似,所以取名字為lambda函式)

python 使用 lambda 來建立匿名函式。

所謂匿名,意即不再使用 def 語句這樣標準的形式定義一個函式。

  1. lambda 只是一個表示式,函式體比 def 簡單很多。
    1. lambda的主體是一個表示式,而不是一個程式碼塊。僅僅能在lambda表示式中封裝有限的邏輯進去。
    2. lambda函式擁有自己的名稱空間,且不能訪問自己引數列表之外或全域性名稱空間裡的引數。
    3. 雖然lambda函式看起來只能寫一行,卻不等同於C或C++的行內函數,後者的目的是呼叫小函式時不佔用棧記憶體從而增加執行效率。

其格式為:lambda 形參(可省略):返回值

lambda方法的使用(無引數)

#使用def定義函式的方法
def true():
    return True
#等價的lambda表示式
>>>lambda : True
<function <lambda> at 0x000001EA532869D8>
#保留lambda物件到變數中,以便隨時呼叫
>>>true = lambda :True
>>>true()
True

lambda方法的使用(有引數)

#使用def定義的函式
def add(x,y):
    return x+y
#使用lambda方法的表示式
lambda x,y:x+y

#lambda也允許有預設值和使用可變長引數
lambda x,y=2:x+y
lambda *args:z

#呼叫lambda函式
>>>a=lambda x,y:x+y
>>>a(1,3)
4
>>>b=lambda x,y=2:x+y
>>>b(1)
3
>>>b(1,3)
4
>>>c=lambda *args:args
>>>c(10,'test')
(10,'test')

使用map()函式將lambda建立的函式作用於一個數據型別的每一個元素中,map函式的原型是map(function, iterable, …),在python3中它的返回結果是一個指標。

引數function傳的是一個函式名,可以是python內建的,也可以是自定義的。
引數iterable傳的是一個可以迭代的物件,例如列表,元組,字串這樣的。

這個函式的意思就是將function應用於iterable的每一個元素,結果以列表的形式返回。注意到沒有,iterable後面還有省略號,意思就是可以傳很多個iterable,如果有額外的iterable引數,並行的從這些引數中取元素,並呼叫function。如果一個iterable引數比另外的iterable引數要短,將以None擴充套件該引數元素。還是看例子來理解吧!
例如:

list(map(lambda x: x * x, [1, 2, 3, 4, 5, 6, 7, 8, 9])) 

使用lambda方法建立一個計算平方的函式,使用map函式將所建立的求平方的函式作用於這個列表中,得到的是指標,然後使用list()函式將其轉化成列表
得到的值為:

[1, 4, 9, 16, 25, 36, 49, 64, 81]

使用lambda函式對列表中的字典進行排序

infors=[{"name":"laoli","age":40},{"name":"xiaoming","age":20},{"name":"banzhang","age":10}]
infors.sort(key=lambda x:x['name'])  #第一個x表示infors列表中的每個元素,lambda方法所定義的函式表示從列表中的每個元素(字典)中去除主鍵出來,然後使用sort方法進行排序
print(infors)

得到的結果為:

[{'name': 'banzhang', 'age': 10}, {'name': 'laoli', 'age': 40}, {'name': 'xiaoming', 'age': 20}]

匿名函式作為實參傳遞給函式

def test(a,b,func):    #設定形參func用來接收實參lambda所建立的函式
    result=func(11,22)       #將11和22傳遞給func函式
    return result            #將程式值返回
num=test(11,22,lambda x,y:x+y) #將lambda所建立的函式作為實參傳遞給func
print(num)    

程式首先執行呼叫函式的那段程式碼,即執行 test(11,22,lambda x,y:x+y),那麼就將11賦值給形參a,12賦值給形參b,lambda所建立的函式賦值給引數func,準確說應該是形參a指向存放數字11的地址才對,,,然後程式執行呼叫函式那段,對於func(11,22)即就是將11和22賦值給lambda所建立的函式的引數x和y,即x=11,y=12,那麼計算的的結果就是result=11+22=33,又將result返回,執行呼叫函式那段程式碼,即num=result=33