目錄wraps裝飾器
import time
print(time.time()) # 顯示此時此刻距離2023年1月1日0點0分0秒的秒數,也叫時間戳。
# 第乙個版本
import time
def func1():
time.sleep(1) # 讓程式停止1秒,模擬程式的執行耗時
print('hello,word!')
start_time = time.time()
func1()
end_time = time.time()
print(end_time - start_time)
# 實現了測試效率的功能,但**寫死,只能測試這裡的func1,如果有多處呼叫func1,那麼要寫大量重複**。
# 第二個版本
import time
def func1():
time.sleep(1)
print('hello,word!')
def timer(f):
start_time = time.time()
f()end_time = time.time()
print(end_time - start_time)
timer(func1)
# 不用寫重複**,並且可以測試其他函式,但改變了函式的呼叫方式
# 第三個版本
import time
def func1():
time.sleep(1)
print('hello,word!')
def timer(f):
def inner():
start_time = time.time()
f() # 裝飾器的本質就是閉包,此時引數f是個自由變數。
end_time = time.time()
print(end_time - start_time)
return inner
func1 = timer(func1) # 傳進函式內的func1並不會改變
func1() # 此時的func1()相當於inner()
# 將timer(func1)的返回值賦值給乙個與被裝飾函式同名的變數名,這樣呼叫者看起來func1並沒有變化。
# 在未改變原**和呼叫方式的基礎上,增加了功能,但多了乙個賦值語句func1 = timer(func1)
# 若是呼叫其他函式則需要重複寫**,所以python做了個優化:提出來語法糖的概念
語法糖。
# 第四個版本
import time
def timer(f): # timer 就是個裝飾器
def inner():
start_time = time.time()
f()end_time = time.time()
print(end_time - start_time)
return inner
@timer # 相當於 func1 = timer(func1) 寫在函式之前
def func1():
time.sleep(1)
print('hello,word!')
return 'in func1'
print(func1())
# 此時func1實際上為inner,原func1的返回值是返回給原func1,並非返回給inner,所以值為none
# 函式定義的正上方加語法糖才會呼叫timer
def func2():
time.sleep(1)
print("i'm fine")
return 'in func1'
func2()
# 此時裝飾器基本實現,但無法接收到被裝飾函式返回值,並且無法接收被裝飾函式傳參,還需要繼續修改
# 版本五
import time
def timer(f):
def inner():
start_time = time.time()
r = f() # func1的呼叫實際在這一行,所以將func()的返回值賦值給r,將r返回給inner
end_time = time.time()
print(end_time - start_time)
return r
return inner
@timer
def func1():
time.sleep(0.5)
print('hello')
return 'in func1'
print(func1())
# 此時func1實際上為inner,inner的返回值為r,也就是原func1的返回值。
# 沒有改變func1的呼叫方式,也沒有改變func1的返回值,符合裝飾器定義,接下來需要解決向func1傳參。
# 版本六
import time
def timer(f):
def inner(*args,**kwargs): # 被裝飾函式可能會接收各種引數,利用*的魔性用法可以接收所有引數
start_time = time.time()
r = f(*args,**args) # *放在函式呼叫能將接收的原組與字典拆分成位置實參和關鍵字實參。
end_time = time.time()
print(end_time - start_time)
return r
return inner
@timer
def func1(n,a='18'):
time.sleep(0.5)
print(f'hello,,今年)
return 'in func1'
print(func1('李白',n='33'))
# 此時裝飾器timer已全部完成,當需要測試某函式的執行效率時,則在被裝飾函式定義前加上語法糖語句即可
def inner(*args,**args):
'''被裝飾函式執行前新增的功能'''
ret = f(*args,**args)
'''被裝飾函式執行後新增的功能'''
return ret
return inner
必須在裝飾器定義之後,且是在被裝飾函式的定義語句正上方使用語法糖,否則會報錯。在語法糖和被裝飾函式之間只能用#
號加注釋,不能用三對單引號或雙引號,會報語法錯誤。
格式: pass
# 注釋1
# 注釋2
def f():
pass
例項:
import time
def inner(*args,**kwargs):
start = time.time()
res = func(*args,**kwargs)
stop = time.time()
print(stop - start)
return res
return inner
def f1(x,y):
c = 0
for i in range(x):
for n in range(y):
c = i + n + c
return c
print(f1(1000,10000)) # 此時f1已經被狸貓換太子,其實是inner(1000,10000)
0.8780503273010254
54990000000
def outer(x,y,z):
def inner(*args,**kwargs):
'''被裝飾函式執行前新增的操作'''
ret = func(*args,**kwargs)
'''被裝飾函式執行後新增的操作'''
return ret
return inner
此時則實現了乙個有參裝飾器,在被裝飾函式定義語句上方使用:
@outer(x,y,z)
# 裝飾器outer括號內的引數可以按需求定義。
def func():
pass
print(f1) # f1已經被換成了inner
為了將裝飾後的函式偽裝的與被裝飾函式更相似,python有個內建的裝飾器wraps,能使呼叫者在檢視裝飾後函式的內建屬性時,看似與原函式一致。
例項:
import time
from functools import wraps
def timmer(func):
@wraps(func)
start = time.time()
res = func(*args, **kwargs)
stop = time.time()
print('run time is:%s' % (stop - start))
return res
def index():
"index函式"
time.sleep(1)
print('from index')
print(index.__name__) # 檢視函式名
help(index) # 檢視函式注釋資訊。
結果:
index
help on function index in module __main__:
index()
index函式
如果將wraps注釋掉:
# @wraps(func)
可以看到記憶體位址並沒有變化,但名字都改變了。
開放 封閉原則
開放 封閉原則 the open closed principle,簡稱ocp 或者叫開 閉原則,意思是說軟體實體 類 模組 函式等等 應該可以擴充套件,但是不可修改。即對於擴充套件時開放的 open for extension 對於更改是關閉的 closed for modification 這樣...
開放封閉原則
開放封閉原則 開放封閉原則 就是軟體實體 類 模組 函式等等 應該可以擴充套件,但是不可修改。這個原則有兩個特徵,乙個是說對於擴充套件是開放的,另乙個是說對於更改時封閉的。軟實體包括 1 專案或軟體產品中按照一定的邏輯規則劃分的模組。2 抽象和類。3 方法。無論模組是多麼的封閉,都會存在一些無法對之...
開放封閉原則
開放封閉原則對於擴充套件是開放的,對於修改是封閉的。所謂開放封閉原則就是軟體實體應該對外擴充套件開發,而對修改封閉。開放封閉原則是所有物件導向原則的核心,軟體設計本身所追求的目標就是封裝變化,降低耦合,而開放封閉原則正是對這一目標最直接的體現。例如之前部落格的計算程式中,起初如果我們想要乙個加法的程...