1. 程式人生 > >閉包函數、無參裝飾器

閉包函數、無參裝飾器

開放 2.0 range 名稱 for 分享 ray 原則 port

閉包函數:函數內部定義函數,成為內部函數。該內部函數包含對外部作用域,而不是對全局作用域名字的引用,那麽該內部函數成為閉包函數。

技術分享
name=‘alex‘     #定義全局變量name=‘alex‘
def func():
    name=‘egon‘  #定義局部變量name=‘egon‘
    def bar():
        print(name)
    return bar    #返回bar函數名

b=func()    #執行func()結果為bar的函數名  相當於b=bar
name=‘haha‘  #重新定義全局變量name=‘haha‘
print(b)    #打印bar
b()       #執行bar(),name=‘egon‘

執行結果: <function func.<locals>.bar at 0x000000000222BAE8> egon
技術分享 技術分享
def func():
    name=‘egon‘
    x=1000000000000000000000
    def bar():
        print(name)
        print(x)
    return bar
f=func()
print(f.__closure__)    #打印出閉包函數外層作用域的變量
print(f.__closure__[0].cell_contents)  #打印出閉包函數外層作用域的第一個變量的值
print(f.__closure__[1].cell_contents)  #打印出閉包函數外層作用域的第一個變量的值
運行結果:
(<cell at 0x0000000001E16528: str object at 0x0000000001E993B0>, <cell at 0x0000000001E16558: int object at 0x0000000001EA3C10>)
egon
1000000000000000000000
技術分享

閉包函數:1 內部函數 2 包含對外部作用域而非全局作用域的引用
閉包函數的特點:
    自帶作用域
    延遲計算

以上兩個實例都是包一層,閉包函數可以包多層:

技術分享
#包兩層的閉包函數
def func():
    name=‘egon‘     #第2層作用域的變量
    def wrapper():
        money=1000      #第1層作用域的變量
        def tell_info():
            print(‘my namn is %s‘ % name)   #使用第2層作用域的變量
            print(‘egon have money %s‘ %(money))    #使用第1層作用域的變量
        print(tell_info.__closure__)        #打印閉包函數的變量
        return tell_info
    return wrapper
w=func()
tell_info=w()
print(tell_info.__closure__[0].cell_contents)  #閉包函數變量位置在定義時就定下來了,不因為使用的順序變化
print(tell_info.__closure__[1].cell_contents)
運行結果:
(<cell at 0x0000000001E16558: int object at 0x000000000048AED0>, <cell at 0x0000000001E16528: str object at 0x0000000001E993B0>)
1000
egon
技術分享

定義閉包函數的基本形式:

技術分享
def 外部函數名():
    內部函數需要的變量
    def 內部函數():
        引用外部變量
    return 內部函數

def deco():
    x=1
    def wrapper():
        print(x)
    return wrapper

wrapper=deco()
print(wrapper)
技術分享 技術分享
#包兩層
def deco1():
    y=2
    def deco():
        x=1
        def wrapper():
            print(x)
            print(y)

        return wrapper
    return deco
deco=deco1()
wrapper=deco()
wrapper()
技術分享

二、無參裝飾器

1、開放封閉原則,對擴展是開放的,對修改是封閉的

2、裝飾器,裝飾器本質可以任意可調用對象,被裝飾的對象也可以是任意
可調用對象,
裝飾器的功能是:
在不修改被裝飾對象源代碼以及調用方式的前提下為期添加新功能

原則:
1.不修改源代碼
2.不修改調用方法
目標:添加新功能

無參裝飾器=高級函數+函數嵌套

基本框架

#這就是一個實現一個裝飾器最基本的架子
def timer(func):
    def wrapper():
        func()
    return wrapper

加上參數

def timer(func):
    def wrapper(*args,**kwargs):
        func(*args,**kwargs)
    return wrapper

加上功能

技術分享
import time
def timer(func):
    def wrapper(*args,**kwargs):
        start_time=time.time()
        func(*args,**kwargs)
        stop_time=time.time()
        print(‘函數[%s],運行時間是[%s]‘ %(func.__name__,stop_time-start_time))
    return wrapper
技術分享

加上返回值

技術分享
import time
def timer(func):
    def wrapper(*args,**kwargs):
        start_time=time.time()
        res=func(*args,**kwargs)
        stop_time=time.time()
        print(‘函數[%s],運行時間是[%s]‘ %(func.__name__,stop_time-start_time))
        return res
    return wrapper
技術分享

使用裝飾器的方法一:

技術分享
import time
def timer(func):
    def wrapper(*args,**kwargs):
        start_time=time.time()
        res=func(*args,**kwargs)
        stop_time=time.time()
        print(‘函數[%s],運行時間是[%s]‘ %(func.__name__,stop_time-start_time))
        return res
    return wrapper

def cal(array):
    res=0
    for i in array:
        res+=i
    return res

cal=timer(cal)
cal(range(100000))

運行結果:
函數[cal],運行時間是[0.0070002079010009766]
技術分享

[email protected]

技術分享
import time
def timer(func):
    def wrapper(*args,**kwargs):
        start_time=time.time()
        res=func(*args,**kwargs)
        stop_time=time.time()
        print(‘函數[%s],運行時間是[%s]‘ %(func.__name__,stop_time-start_time))
        return res
    return wrapper
@timer
def cal(array):
    res=0
    for i in array:
        res+=i
    return res

cal(range(100000))
函數[cal],運行時間是[0.007000446319580078]
技術分享

上課實例:

技術分享
#裝飾器修訂
import time
import random
#裝飾器
def timmer(func):
    def wrapper(*args,**kwargs):
        start_time = time.time()
        res=func(*args,**kwargs)
        stop_time=time.time()
        print(‘run time is %s‘ %(stop_time-start_time))
        return res
    return wrapper
#被裝飾函數

@timmer
def index():
    time.sleep(random.randrange(1,5))
    print(‘welecome to index page‘)
@timmer
def home(name):
    time.sleep(random.randrange(1,3))
    print(‘welecome to %s HOME page‘ %name)
    return 1231231231

index()

res1=index()
print(‘index return %s‘ %res1)
res2=home(‘egon‘) #wraper()
print(‘home return %s‘ %res2)


運行結果:
welecome to index page
run time is 2.0001144409179688
welecome to index page
run time is 3.001171350479126
index return None
welecome to egon HOME page
run time is 1.0000574588775635
home return 1231231231
技術分享

閉包函數、無參裝飾器