一个加法函数,想增加它的功能,能够输出被调用过以及调用的参数信息
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