【发布时间】:2018-02-01 18:23:22
【问题描述】:
我试图了解如何编写一个装饰器来检查每个方法的 main_val 属性,尤其是当 main_val 属性的位置可能发生变化,甚至有默认值时。另外,有没有更 Pythonic 的方式来应用这个条件?
我在下面写了一个例子来形象地描述这个问题,希望有更多经验的人能解释一下。
对于下面的每个方法,main_val 应该是我的装饰器应该检查的唯一属性。我不确定如何强制装饰器始终检查 main_val,除非它作为 key=value 属性传递或引用 *args 中的硬编码位置。
class TestCase:
def __init__(self):
self.allowable_list = [1,2,3,4,5]
def decorator_check(func):
# I want to apply condition to "main_val" attribute of any method this decorator is applied to
def wrapper(self, val, *args, **kwargs):
if val not in self.allowable_list:
raise AttributeError("value {} not in allowable list {}".format(val, self.allowable_list))
return func(self, val, *args, **kwargs)
return wrapper
@decorator_check
def calc(self, main_val, val_num_two, val_num_three):
print("(calc) - main_val: {} val_num_two: {} val_num_three: {}".format(main_val, val_num_two, val_num_three))
return main_val * val_num_two * val_num_three
@decorator_check
def calc_two(self, another_val, main_val, val_num_two):
print("(calc_two) - another_val: {} main_val: {} val_num_two: {}".format(another_val, main_val, val_num_two))
return another_val * main_val * val_num_two
@decorator_check
def calc_three(self, another_val, val_num_two, main_val=3):
print("(calc_two) - another_val: {} main_val: {} val_num_two: {}".format(another_val, main_val, val_num_two))
return another_val * val_num_two * main_val
test_obj = TestCase()
test_obj.calc(100, 2 ,3)
按预期返回错误
test_obj.calc_two(2, 5, 3)
返回 (calc_two) - another_val: 2 main_val: 5 val_num_two: 3
test_obj.calc_three(2,5,100)
返回 (calc_two) - another_val: 2 val_num_two: 5 main_val: 100
有什么方法可以解决这个问题?
【问题讨论】:
-
这与您的主要问题无关,但
AttributeError在您使用它的情况下肯定不是正确的例外。该错误表明属性查找obj.attr失败,因为attr不存在。我认为您可能应该改用ValueError,因为当您将错误值的参数传递给函数或方法时,通常会引发这种情况。由于您的装饰器正在根据允许值列表检查您传递的值,这似乎是最合适的。 -
谢谢@Blckknght!我只是查看了定义,并没有意识到是这样的。
标签: python python-3.x decorator