Stories

Detail Return Return

2019-07-11 閉包函數和裝飾器 - Stories Detail

一、閉包函數

  定義:定義在內部的函數引用外部函數的名字(變量)叫做閉包函數

  要打印的是inner函數的x,因為這個函數裏面沒有定義x的值,所以找上一層的局部變量x = 111。執行代碼,outter函數被調用,返回值為inner,用變量res接收,所以res = inner,下面再用res(),就是inner(),調用inner函數,執行裏面代碼,打印結果為111

def outter():
    x = 111
    def inner():
        print(x)
    return inner
res = outter()  # res就是inner函數內存地址
res()    #111

  給函數體傳值的兩種方式:

    1.函數調用時候直接傳參

def index1(username):
    print(username)
res = index1('aa')      #aa

    2.閉包傳參

  這個和剛開始定義的閉包函數一樣只不過是把變量x,y放在outter函數裏面當形參,在調用的時候傳實參

def outter(x,y):
    # x = 1
    # y = 40
    def my_max():
        if x > y:
            return x
        return y
    return my_max
res1 = outter(1,40)  # res就是my_max函數的內存地址
print(res1())    #40

 

二、裝飾器

  定義:給被裝飾的對象添加新的功能的一個工具。  目的:更方便的使用新添加的新功能

  裝飾器(可調用對象)必須遵守的兩個原則:

    1.不可改變被裝飾對象的代碼

    2.不可改變 被裝飾對象的調用方式(假如調用方式是idnex(),使用裝飾器之後也是這種調用方式)

  

  簡單版本:

  在原始函數index函數上加一個時間計算功能,最後也是調用了index(),沒有違反裝飾器的兩個原則。運行函數先到outter調用,裏面傳一個參數index(這個是最原始的index函數的內存地址),然後返回get_time,用變量index接收。index()其實就是調用get_time函數。執行裏面代碼,func()就是之前傳的func參數,index()調用。

import time
def index():
    time.sleep(3)
    print('睡醒了')

def outter(func):  # func = 最原始的index函數的內存地址
    def get_time():
        start = time.time()
        func()  # func = index函數的內存地址() 直接調用
        end = time.time()
        print('index run time:%s'%(end-start))
    return get_time
index = outter(index)  # outter(最原始的index函數內存地址)
# index指向get_time函數的內存地址
index()   #睡醒了

  升級版本:(被裝飾的函數需要參數,之前的用法需要在get_time裏面的func()寫參數,才能使用正確。統一參數寫法:*args,**kwargs)

import time
def index():
    time.sleep(3)
    print('澳門最大線上賭場開業啦 性感tank在線發牌!')
    return 'index'
# res1 = index()

def login(name):
    time.sleep(1)
    print('%s is sb'%name)
    return 'login'
# res = login('egon')

def outter(func):  # func = 最原始的login函數的內存地址
    def get_time(*args, **kwargs):  # args = ('egon',) kwargs = {}
        start = time.time()
        res = func(*args, **kwargs)  # 最原始的login函數的內存地址() 直接調用  func('egon')
        end = time.time()
        print('func run time:%s'%(end-start))
        return res
    return get_time
login = outter(login)  # outter(最原始的login函數的內存地址)
res = login('egon')
print(res)
index = outter(index)
res1 = index()
print(res1)
代碼

  這樣設置之後可以接受任意參數的函數。

 三、裝飾器語法糖

  語法糖在書寫的時候應該與被裝飾器緊緊挨着,兩者之間不要有空。把裝飾器賦值給緊挨這的的可調用對象,並且把緊挨着的函數名當做參數傳遞到裝飾器中

 

def outter(func):
    def inner(*args,**kwargs):
        #調用被裝飾對象 (為被裝飾對象添加新功能)
        func(*args,**kwargs)
        print('inner')
    return inner

@outter   #index = outter(index)  -->  index = inner
def index():
    print('index')
index() # -->inner()

  

四、多個裝飾器一起使用

   注意:裝飾器裝飾順序:從下往上

        裝飾器執行效率:從上往下

 

 

 

Add a new Comments

Some HTML is okay.