裝飾器後端
你是一家互聯網公司的後端攻城獅,大家公司有一個現有函數以下:函數
import time
def add(x,y):
print(x + y)
time.sleep(5)
#add(5,9)
如今TEAM LEADER要讓你對函數進行擴展,要求在函數執行以前打印時間,執行以後打印時間,你可能很快就完成了任務,代碼以下:spa
import time
def add(x,y):
print(time.time())
print(x + y)
time.sleep(5)
print(time.time())
add(5,9)
此時你信心滿滿的把這個代碼提交給你的TEAM LEADER審覈,沒成想,沒過5分鐘,代碼就被打回來了, TEAM LEADER給你反饋是,我如今有不少函數須要加這個功能,你的代碼雖然實現了功能,可是須要更改各個函數的代碼,這直接違反了軟件開發中的一個原則「開放-封閉」原則,簡單來講,它規定已經實現的功能代碼不容許被修改,但能夠被擴展,即:code
封閉:已實現的功能代碼塊不該該被修改對象
開放:對現有功能的擴展開放開發
BUT ANYWAY,老大要求的這個怎麼實現呢?如何在不改原有功能代碼的狀況下io
加上認證功能呢?咱們以前說太高階函數,就是把一個函數當作一個參數傳給另一個函數,下面就用高階函數來實現它function
import time
def add(x,y):
print(x + y)
time.sleep(5)
定義一個函數
def show_time(f):
def inner(x,y):#***********這裏的參數對應函數f的參數
print(time.time())
f(x,y)
print(time.time())
return inner
則執行show_time(add)返回一個函數對象inner
print(show_time(add))#<function show_time.<locals>.inner at 0x0000000001F00268>
函數對象加括號就會執行函數,則
咱們將show_time(add)返回的值賦給一個變量add
add = show_time(add)
再執行add,就實現功能了
add(1,2)
這樣咱們在沒有修改原函數的前提下,實現了這個功能,此時無論什麼函數須要這個功能,你只要:函數名 = show_time(函數名) ,而後執行這個函數就能夠了,爲了代碼更加簡潔,咱們採用註解的方式代替 函數名 = show_time(函數名),只須要在添加功能的函數上方加一行註解:import
import time
def show_time(f):
def inner(x,y):#***********這裏的參數對應函數的參數
print(time.time())
f(x,y)
print(time.time())
return inner
@show_time
def add(x,y):
print(x + y)
time.sleep(5)
add(5,9)
@show_time 就至關於 add = show_time(add),@show_time 就是一個裝飾器。變量
裝飾器有參數的狀況
import time
def logger(flag):#這裏參數控制是否打印時間
def show_time(f):#這裏參數對應函數
def inner(*x, **y): # ***********這裏的參數對應函數的參數
start = time.time()
f(*x, **y)
end = time.time()
if flag == True:
print(end - start)
return inner
return show_time
@logger(True)
def add1(*x,**y):
sum = 0
for i in x:
sum += i
print(sum)
time.sleep(4)
add1(1,2,3,4,5,6)
分析:執行 logger(True)返回show_time
因此 @logger(True) 至關於 @show_time,只是多加了一個條件,讓使用變得更加靈活。
深淺拷貝
淺拷貝 copy(只拷貝第一層,裏面層仍指向原來的對象)
s = [[1, 2], 'aaa', 'bbb']
s2 = s.copy() #第一層的數據都拷貝一份
s2[0][0] =888 #修改後s[0][0]也會變,他們指向同一個對象
s2[1] = 'www' #修改後s[1]不會變,各有各的對象
print(s2) #[[888, 2], 'www', 'bbb']
print(s) #[[888, 2], 'aaa', 'bbb']
深拷貝
須要引入copy模塊
import copy
s = [[1, 2], 'aaa', 'bbb']
s3=copy.deepcopy(s) #全部層都複製一份,各是各的,互不影響。
s3[0][1] = 666
print(s3) #[[1, 666], 'aaa', 'bbb']
print(s) #[[1, 2], 'aaa', 'bbb']