python - 如何将参数作为装饰器发送给类?
问题描述
我有以下演示脚本,其中有两个装饰器(嵌套)。一个是validNumber
函数返回包装器,用于测试传递给装饰函数的参数是否为正,另一个addExtra
是一个类,将前一个装饰器的输出加上一个。
def validNumber(f):
def wrapper(*args):
for arg in list(args):
if arg < 0:
raise AttributeError('The number can\'t be negative')
return f(*args)
return wrapper
class addExtra:
def __init__(self, fun):
self.fun = fun
def __call__(self, *args):
total = self.fun(*args)
if total < 100:
total += 1 # I want to make it dynamic.
return total
@addExtra
@validNumber
def sumOfNumbers(*args):
return sum(list(args))
现在如您所见,我手动将“1”添加到参数总数中。但我想让它动态化。喜欢:
@addExtra(4) # add 4 to the total
@addExtra(2) # add 2 to the total
更新 由于社区提出了另一个具有类似问题的问题。我执行以下操作
class addExtra:
def __init__(self, extra):
self.extra = extra
def __call__(self, fun):
@functools.wraps(fun)
def decorated(*args, **kwargs):
total = fun(*args)
if total < 100:
total += self.extra # I want to make it dynamic.
return total
return decorated
并得到
TypeError: call () 接受 2 个位置参数,但给出了 4 个
有人可以在这里解释一下,而不是重定向到其他问题或答案吗?甚至我也想知道这里@functools.wraps 的使用。
解决方案
为了能够将参数传递给您的装饰器,您必须创建一个返回装饰器的函数。
def addExtra(number):
def decorator(*args, **kwargs):
def wrapper(fun):
total = fun(*args, **kwargs)
if total < 100:
total += number
return total
return wrapper
推荐阅读
- swift - Swift 在递归使用时假定泛型类型
- android - 'com.google.android.gms.drive.Drive' 已弃用
- scala - Scala 通用查询谓词生成 DSL(可能类似于 javascript 中的 AlaSQL)?
- doxygen - GNURadio 如何从克隆的 repo 中查看内部 doxygen 文档?
- php - 在 php 中找到没有任何库的 Telegram 频道成员计数
- laravel-5 - vuejs/vuex app的用户刷新页面logged怎么处理?
- javascript - 提供的音量超出范围 [0, 1] 错误
- php - Composer 在新宅基地上使用 kylekatarnls/update-helper 失败
- excel - 如果它们是某种其他颜色,如何改变细胞的颜色?
- php - 如何在php中将时间戳转换为正常时间