大家好,我是金鱼座,一个走在测试领域这片蓝海中, 蹉跎前行的技术渣渣,唯有一直走下去,也许能改变点什么,加油!
今天看到一个有趣关于装饰器活用的一种表达,之前在使用装饰器的时候,我们很多时候都是有参数,无参数等进行区分,比如一个典型的装饰器函数有参数的情况
def log2(param):
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
if not param:
print('%s no param' % (param))
else:
print('%s in %s()' % (param, func.__name__))
return func(*args, **kwargs)
return wrapper
return decorator
@log2("")
def now3():
print("now3")
@log2("test")
def now4():
print("now4")
如上代码可以看出就是一个普通装饰器方法带参数的例子,通过参数的判断来调整输出,结果如下:
image.png
那么如果我想实现一种如下图的装饰器显示方式,那个该怎么处理呢??
如图片所示,我想用一个装饰器方法名既能充当有参数的情况,也能充当无参数的情况
这是一个很好的方式, 废话就不说了,上代码
import functools
def log(param):
# 不存在可调用对象的情况下
if callable(param):
def wrapper(*args, **kwargs):
print('%s function()' % (param.__name__,))
param(*args, **kwargs)
return wrapper
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kw):
print('%s %s():' % (param, func.__name__))
return func(*args, **kw)
return wrapper
return decorator
如代码所示,通过callable来判断当前是否是可调用对象,如果是可调用对象则作为无参数来进行使用,如果不是一个可调用对象,则作为一个普通参数来处理
image.png
至于为什么是这个情况呢?
下面简单说一下自己的理解
我们应该知道作为一个装饰器他们再执行的时候,是具有一下特点的,为了方便找了一个截图
image.png
如图所示 一个 @log 等于 如下表达:
t = log(f1) 通过return wrapper返回执行对象
t()
通过这表达式来解读上面的实现原来就可以明白
image.png
通过判断当前的这个param是否是f1这个方法的对象,如果是方法的对象则理解为普通的@log装饰器,如果是这个param不是一个f1这个对象而是一个普通的“测试‘这个参数,那么就当作一个@log(”测试')来进行处理
这就是上面之所以可以实现合并表达的主要原因
当然这些都是自己的一种理解认知,如果有不合适的地方,也欢迎朋友指正,谢谢
网友评论