開放封閉原則和裝飾器

2022-06-26 02:51:09 字數 4923 閱讀 5986

目錄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 方法。無論模組是多麼的封閉,都會存在一些無法對之...

開放封閉原則

開放封閉原則對於擴充套件是開放的,對於修改是封閉的。所謂開放封閉原則就是軟體實體應該對外擴充套件開發,而對修改封閉。開放封閉原則是所有物件導向原則的核心,軟體設計本身所追求的目標就是封裝變化,降低耦合,而開放封閉原則正是對這一目標最直接的體現。例如之前部落格的計算程式中,起初如果我們想要乙個加法的程...