python怎麼傳參數,怎麼寫裝飾器decorator()

2018.03.12
author: wills

在python中,不管是傳一個參數,還是多個參數,又或者部分參數要求參數名,部分參數不需要函數名,都有嚴格的語法要求。

一,多個參數,不知道有沒有參數名

def say_hello(*args,**kwargs):


def say_hello(*args,**kwargs):
    if 'name' in kwargs:
        print('你好,%s!' % kwargs['name'])
    elif 'age' in kwargs:
        age = kwargs['age']
        if age <= 15:
            print('你還小')
        else:
            print('你是大人了')
    else:
        print('你是誰')
    print(args)
    print(kwargs)

關鍵字參數(**kwargs) :傳進來—->一個字典—->根據參數名決定如何執行

可變參數(*args):傳進來的是一個元組tuple

如果想直接傳字典作爲可變關鍵字參數,需要在字典前面加 ‘**’

    dict1 = {'name':'will','age':22}
    say_hello(**dict1)

如果直接傳元組,列表作爲可變參數,需要在元組,列表前加 ‘*’

    tuple = (1,2,34,5)
    say_hello(*tuple)

命名關鍵字參數

## 命名關鍵字參數 ,* 後面的參數,必須給參數名,前面的可給可不給
def foo(a,e,d,*,name,age):
    print(a+e+d)
    print('%s' % name +':'+'%s' % age)

foo(a=1,d=33,e=123,name='gppd',age=12)
foo(2,2,3,name='will',age=85)

高階函數

爲了提高函數的通用性,又要符合函數高內聚的特性,我們可以把簡單函數當做參數傳入函數裏,構成一個根據參數不同實現不同功能的高級函數,這就是高階函數。見下例

def cal(list,op):
    total = list[0]
    for x in range(1,len(list)):      
        total = op(total,list[x])
    return total 
# 通過向函數中傳入函數,可以寫出更通用的代碼
# cal 函數中第二個參數是另一個函數,他代表了一個二元運算
# 這樣cal函數就不需要和某個特定二元運算耦合在一起
# 所以cal函數變得通用性更強,可以由傳入的第二個參數決定函數到底做什麼
# 高內聚,低耦合  high cohesion low coupling
# 高內聚:函數做好一件事就好了
def add(x,y):
    return x+y
def mul(x,y):
    return x * y

lis=[1,3,5]
print(cal(lis,add))
print(cal(lis,mul))

很重要的函數方法decorator(),它的作用是裝飾另一個函數使得另一個函數自身不變的情況下擁有更多的功能

def record(fn):
    def wrapper(*args,**kwargs):
        print('準備執行%s函數 ' % fn.__name__)
        print(args)
        print(kwargs)

        # 此時正在執行被裝飾的函數
        # 在這行代碼的前後我們可以附加其他代碼
        # 這些代碼可以讓我們在執行函數時做一些額外的工作
        val = fn(*args,**kwargs)

        print('執行%s函數之後。。。' % fn.__name__)
        print('return %d' %val)      
        return val
        # 返回被裝飾函數的執行結果       
    return wrapper

# 通過裝飾器修飾f函數,讓f函數在執行時可以做更多額外的操作
@record
def f(n):
    if n == 0 or n == 1:
        return 1
    return n * f(n-1)

if __name__ == '__main__':
    print(f(5))

命名關鍵字參數 ,* 後面的參數,必須給參數名,前面可給可不給

def foo(a,e,d,*,name,age):
    print(a+e+d)
    print('%s' % name +':'+'%s' % age)

foo(a=1,d=33,e=123,name='gppd',age=12)
foo(2,2,3,name='will',age=85)
def record(fn):
    def wrapper(*args,**kwargs):
        print('準備執行%s函數 ' % fn.__name__)
        print(args)
        print(kwargs)

        # 此時正在執行被裝飾的函數
        # 在這行代碼的前後我們可以附加其他代碼
        # 這些代碼可以讓我們在執行函數時做一些額外的工作
        val = fn(*args,**kwargs)

        print('執行%s函數之後。。。' % fn.__name__)
        print('return %d' %val)      
        return val
        # 返回被裝飾函數的執行結果

    return wrapper
# 通過裝飾器修飾f函數,讓f函數在執行時可以做更多額外的操作
@record
def f(n):
    if n == 0 or n == 1:
        return 1
    return n * f(n-1)

if __name__ == '__main__':
    print(f(5))

下面就是遞歸求階乘函數被裝飾後運行過程,可以更清楚的看到被裝飾函數f(n)每一步是怎麼運行的

準備執行f函數
(5,)
{}
準備執行f函數
(4,)
{}
準備執行f函數
(3,)
{}
準備執行f函數
(2,)
{}
準備執行f函數
(1,)
{}
執行f函數之後。。。
return 1
執行f函數之後。。。
return 2
執行f函數之後。。。
return 6
執行f函數之後。。。
return 24
執行f函數之後。。。
return 120
120

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章