一個加法函數,想增加它的功能,能夠輸出被調用過以及調用的參數信息
def add(x, y):
return x + y
增加信息輸出功能:
def add(x, y):
print("call add, x + y") #日誌輸出到控制檯
return x + y
缺點:
打印語句的耦合太高
加法函數屬於業務功能,而輸出信息屬於非業務功能代碼,不該放在業務中
def add(x, y):
return x + y
def logger(fn):
print('begin') # 增加的輸出
x = fn(4, 5)
print('end') # 增加的功能
return x
print(logger(add))
做到了業務功能分離,但是fn函數調用傳參是個問題
def add1(x, y):
return x + y
def add2(x, y, z):
return x + y + z
def add3(x, y, *args, z, **kwargs):
return x + y + z
def logger(fn, *args, **kwargs):
print('begin')
a = fn(*args, **kwargs)
print('end')
return a
print(logger(add1, 5, y=61))
print(logger(add2, 5, 8, z=62))
print(logger(add3, 5, 7, z=63))
def add3(x, y, *args, z, **kwargs):
return x + y + z
def logger(fn): # 柯里化
def looper(*args, **kwargs): # *可變參數
print('begin')
a = fn(*args, **kwargs) # *參數解構
print('end')
return a
return looper
print(logger(add3)(5, 7, z=63))
裝飾器:
def logger(fn): # 柯里化
def _logger(*args, **kwargs):
print('begin')
a = fn(*args, **kwargs)
print('end')
return a
return _logger
@logger # add3 = logger(add3)
def add3(x, y, *args, z, **kwargs):
return x + y + z
print(add3(4, 6, z=5))
import datetime
import time
def logger(fn):
def wrap(*args, **kwargs):
print("before") # 調用前增強
start = datetime.datetime.now()
ret = fn(*args, **kwargs)
print("after") # 調用後增強
duration = datetime.datetime.now() - start
print("function {} took {}s".format(fn.__name__, duration.total_seconds()))
return ret
return wrap
@logger
def add(x, y):
print("----call add----")
time.sleep(2)
return x + y
print(add(4, 9))
import datetime
import time
def logger(fn):
def wrap(*args, **kwargs):
'''
this a wrapper function
:param args:
:param kwargs:
:return:
'''
print("before") # 調用前增強
start = datetime.datetime.now()
ret = fn(*args, **kwargs)
print("after") # 調用後增強
duration = datetime.datetime.now() - start
print("function {} took {}s".format(fn.__name__, duration.total_seconds()))
return ret
return wrap
@logger
def add(x, y):
'''
this is a add function
:param x:
:param y:
:return:
'''
print("----call add----")
time.sleep(2)
return x + y
print(add(4, 9), add.__doc__, add.__name__, sep='\n')
# 這樣輸出的文檔是wrap的,名字也是wrap的,需求是業務函數的信息
import datetime
import time
def copy_properties(src, dst): # 可以改爲裝飾器
dst.__doc__ = src.__doc__
dst.__name__ = src.__name__
def logger(fn):
def wrap(*args, **kwargs):
'''
this a wrapper function
:param args:
:param kwargs:
:return:
'''
print("before") # 調用前增強
start = datetime.datetime.now()
ret = fn(*args, **kwargs)
print("after") # 調用後增強
duration = datetime.datetime.now() - start
print("function {} took {}s".format(fn.__name__, duration.total_seconds()))
return ret
copy_properties(fn, wrap)
return wrap
@logger
def add(x, y):
'''
this is a add function
:param x:
:param y:
:return:
'''
print("----call add----")
time.sleep(2)
return x + y
print(add(4, 9), add.__doc__, add.__name__, sep='\n')
out:
before
----call add----
after
function add took 2.000802s
13
this is a add function
:param x:
:param y:
:return:
add
# 這樣就OK了
import datetime
import time
def copy_properties(src): # 拷貝業務函數屬性
def _copy(dst):
dst.__doc__ = src.__doc__
dst.__name__ = src.__name__
dst.__qualname__ = src.__qualname__
return dst
return _copy
def logger(fn):
@copy_properties(fn) # ---> copy_properties(add) --> @_copy --> wrap = _copy(wrap)
def wrap(*args, **kwargs):
'''
this a wrapper function
:param args:
:param kwargs:
:return:
'''
print("before") # 調用前增強
start = datetime.datetime.now()
ret = fn(*args, **kwargs)
print("after") # 調用後增強
duration = datetime.datetime.now() - start
print("function {} took {}s".format(fn.__name__, duration.total_seconds()))
return ret
return wrap
@logger
def add(x, y):
'''
this is a add function xxxxxxx
:param x:
:param y:
:return:
'''
print("----call add----")
time.sleep(2)
return x + y
print(add(4, 9), add.__doc__, add.__name__, add.__qualname__, sep='\n')
import datetime
import time
def copy_properties(src):
def _copy(dst):
dst.__doc__ = src.__doc__
dst.__name__ = src.__name__
dst.__qualname__ = src.__qualname__
return dst
return _copy
def logger(t1, t2):
def _logger(fn):
@copy_properties(fn)
def wrap(*args, **kwargs):
'''
this a wrapper function
:param args:
:param kwargs:
:return:
'''
print("before") # 調用前增強
start = datetime.datetime.now()
ret = fn(*args, **kwargs)
print("after") # 調用後增強
duration = (datetime.datetime.now() - start).total_seconds()
print("function {} took {}s".format(fn.__name__, duration)) if duration < t1 else print("so slow")
# if t2 > duration > t1:
# print(".....")
return ret
return wrap
return _logger
@logger(3, 6) # add = logger(3)(add) = _logger(add) 帶參裝飾器
def add(x, y):
'''
this is a add function xxxxxxx
:param x:
:param y:
:return:
'''
print("----call add----")
time.sleep(4)
return x + y
print(add(4, 9), add.__doc__, add.__name__, add.__qualname__, sep='\n')
import datetime
import time
import functools
def logger(t1, t2):
def _logger(fn):
#@functools.wraps(fn) # 可以直接用裝飾器 functools.update_wrapper(wrap, fn)
def wrap(*args, **kwargs):
'''
this a wrapper function
:param args:
:param kwargs:
:return:
'''
print("before") # 調用前增強
start = datetime.datetime.now()
ret = fn(*args, **kwargs)
print("after") # 調用後增強
duration = (datetime.datetime.now() - start).total_seconds()
print("function {} took {}s".format(fn.__name__, duration)) if duration < t1 else print("so slow")
# if t2 > duration > t1:
# print(".....")
return ret
functools.update_wrapper(wrap, fn) # 可被上面的註釋行替代
print("{} {}".format(id(wrap), id(fn))) # id可以看到是裝飾函數,還是被裝飾的函數
return wrap
return _logger
@logger(3, 6) # add = logger(3)(add) = _logger(add)
def add(x, y):
'''
this is a add function xxxxxxx
:param x:
:param y:
:return:
'''
print("----call add----")
time.sleep(4)
return x + y
print(add(4, 9), add.__doc__, add.__name__, add.__qualname__, sep='\n')
print("############")
print(add.__wrapped__)
print(id(add.__wrapped__))
out:
2149881420792 2149881028952(被包裝函數add)
before
----call add----
after
so slow
13
this is a add function xxxxxxx
:param x:
:param y:
:return:
add
add
############
<function add at 0x000001F48EE52158>
2149881028952 (被包裝函數add,也就是說add.__wrapped__屬性是add的)
import datetime
import time
import functools
def logger(t1, t2, func=lambda name, duration: print('{} took {}s'.format(name, duration))):
def _logger(fn):
@functools.wraps(fn)
def wrap(*args, **kwargs):
'''
this a wrapper function
:param args:
:param kwargs:
:return:
'''
print("before") # 調用前增強
start = datetime.datetime.now()
ret = fn(*args, **kwargs)
print("after") # 調用後增強
duration = (datetime.datetime.now() - start).total_seconds()
func if duration < t1 else print("so slow")
# if t2 > duration > t1:
# print(".....")
return ret
# functools.update_wrapper(wrap, fn)
print("{} {}".format(id(wrap), id(fn)))
return wrap
return _logger
@logger(2, 6) # add = logger(3)(add) = _logger(add)
def add(x, y):
'''
this is a add function xxxxxxx
:param x:
:param y:
:return:
'''
print("----call add----")
time.sleep(4)
return x + y
print(add(4, 9), add.__doc__, add.__name__, add.__qualname__, sep='\n')
print("############")
print(add.__wrapped__)
print(id(add.__wrapped__))
這版OK