閉包函數、無參裝飾器
阿新 • • 發佈:2017-06-20
開放 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
閉包函數、無參裝飾器