1. 程式人生 > >閉包與裝飾器

閉包與裝飾器

函數名 for循環 a + b 使用 style 裝飾 post 內存地址 lee

一、函數名

  函數名在本質上就是函數的內存地址,函數名有以下功能:

    函數名可以賦值給別的變量;;

    函數名還可以當做容器類型裏面的元素,(列表、字典);

    函數名可以當做函數的參數和返回值;具體實例如下:

技術分享圖片
#!/usr/bin/python
# -*- encodeing:utf-8 -*-
# 函數可以賦值給別的變量
# def func():
#     print(‘caoyf‘)
# a = func # 此函數名賦值給了變量‘a‘,在下面直接輸入a()就相當於調用func函數
# a()

#函數名可以當做容器類型的元素:例如:列表
# def func():
#
print(‘我是func函數‘) # def inner(): # print(‘我是inner函數‘) # def caoyf(): # print(‘我是曹艷飛函數‘) # a = [func,inner,caoyf] # 列表的查詢方式可以通過切邊進行查看,為了方便查看所有結果,使用for循環一次查看所有的結果 # for i in a: # i() # 函數名可以當做函數的參數和返回值使用: # def func(): # print(‘func函數‘) # def inner(name): # name() # return name
# a = inner(func) # print(a)
函數名

二、閉包

  函數的閉包定義:

    在函數內部再定義一個函數,並且這個函數用到了外邊函數的變量,那麽將這個函數以及用到的一些變量稱之為閉包,實例如下:

技術分享圖片
#!/usr/bin/python
# -*- encodeing:utf-8 -*-
# 內部函數調用外部函數的變量
# def func(a):
#     def inner(b):
#         return a + b # 在inner函數裏面調用了func函數的變量a,然後將inner返回給調用者
#     return  inner
# ret = func(30)(20)
# print(ret)
內部函數調用外部函數的變量

    內部函數對外部函數作用域變量的引用(非全局變量),則成為內部函數為閉包,實例如下:

    判斷一個函數是不是閉包,可以使用__closure__方法測試,如果打印出來的是cell那這就是一個閉包,如果打印的是None,那就不是閉包,實例如下:

技術分享圖片
#!/usr/bin/python
# -*- encodeing:utf-8 -*-
# def func():
#     name = ‘caoyf‘
#     def inner():
#         print(name)
#     return inner
# ret = func() # inner函數裏面調用了func函數的變量name。
# ret()
# 判斷是不是閉包
# def func():
#     name = ‘caoyf‘
#     def inner():
#         print(name)
#     print(inner.__closure__) #這個函數是一個閉包,因為inner函數裏面調用了func函數的變量name。
#     return inner
# ret = func()
# ret()

# def func():
#     name = ‘caoyf‘
#     def inner():
#         print(666666)
#     print(inner.__closure__)
#     inner() #這個函數就不是閉包,因為內部沒有引用外部的變量
# ret = func()
閉包與判斷是不是閉包

三、裝飾器

   現在有這麽一個開發需求,領導想知道每段代碼的耗時時間,來評比工作的考核

  一般開發的代碼內容如下:  

#!/usr/bin/python
# -*- encodeing:utf-8 -*-
def func():
    print(執行此段代碼,你會看到意想不到的結果)

  靈機一動,寫了下面的代碼:

技術分享圖片
#!/usr/bin/python
# -*- encodeing:utf-8 -*-
import time
def func():
    start = time.time()
    time.sleep(0.1)  # 假設為執行時間,實際代碼肯定不是一個print能搞定的
    print("執行此段代碼,你會看到意想不到的結果")
    end = time.time()
    print(func函數共用時%s %(end - start))
func()
View Code

  在接下來的幾天時間裏,開發的同事看見我都想打死我,我有趕緊的把原來的代碼拿出來進行修改,於是又出來了下面的版本,同時告訴大家以後再使用的時候直接調用timeer函數就行了;

技術分享圖片
#!/usr/bin/python
# -*- encodeing:utf-8 -*-
# import time
# def func():
#     print(‘執行此段代碼,你會看到意想不到的結果‘)
# def timeer(func):
#     start = time.time()
#     func()
#     end = time.time()
#     print(‘func函數共用時%s‘ %(start - end))
# f1 = func
# func = timeer
# func(f1)
time函數

  後來有人告訴我裏面的代碼還可以節儉,可以使用語法糖的方式,這樣同事在計算時間的函數前加一句@timeer就可以了,於是又出了一個版本;

技術分享圖片
#!/usr/bin/python
# -*- encodeing:utf-8 -*-
import time
def timeer(f):
    def inner():
        start = time.time()
        f()
        end = time.time()
        print(func函數共用時%s %(start - end))
    return inner
@timeer
def func():
    print(執行此段代碼,你會看到意想不到的結果)
func()
@語法糖

  為了方便後期開發同事的使用,有修改了一次版本,增加了帶有參數的和返回值的,以下是萬能版本的timeer函數裝飾器:

技術分享圖片
#!/usr/bin/python
# -*- encodeing:utf-8 -*-
import time
def timeer(f):
    def inner(*args,**kwargs):
        start = time.time()
        ret = f(*args,**kwargs)
        end = time.time()
        print(func函數共用時%s %(start - end))
        return ret
    return inner
@timeer
def func(*args):
    print(執行此段代碼,你會看到意想不到的結果 %s%args)
func(www.xxxooo.com)
萬能裝飾器

    

    

閉包與裝飾器