【发布时间】:2017-08-04 22:23:36
【问题描述】:
我正在编写几个函数,它们接受一个名为policy 的参数,它只允许具有某些值(即'allow' 或'deny')。如果没有,我希望提出ValueError。
为简洁起见,我想为此定义一个装饰器。到目前为止,我想出了以下几点:
def validate_policy(function):
'''Wrapper which ensures that if the function accepts a 'policy' argument, that argument is either 'allow' or 'deny'.'''
def wrapped_function(policy, *args, **kwargs):
if policy not in ['allow', 'deny']:
raise ValueError("The policy must be either 'allow' or 'deny'.")
return function(policy, *args, **kwargs)
return wrapped_function
问题在于,这仅在 policy 是函数的第一个位置参数时才有效。但是,我想允许policy 出现在任何位置。
具体来说,这里有一些称为 make_decision 和 make_informed_decision 的(虚拟)函数,它们在不同的位置接受参数 policy,以及一些测试用例:
import pytest
@validate_policy
def make_decision(policy): # The 'policy' might be the first positional argument
if policy == 'allow':
print "Allowed."
elif policy == 'deny':
print "Denied."
@validate_policy
def make_informed_decision(data, policy): # It also might be the second one
if policy == 'allow':
print "Based on the data {data} it is allowed.".format(data=data)
elif policy == 'deny':
print "Based on the data {data} it is denied.".format(data=data)
'''Tests'''
def test_make_decision_with_invalid_policy_as_positional_argument():
with pytest.raises(ValueError):
make_decision('foobar')
def test_make_decision_with_invalid_policy_as_keyword_argument():
with pytest.raises(ValueError):
make_decision(policy='foobar')
def test_make_informed_decision_with_invalid_policy_as_positional_argument():
with pytest.raises(ValueError):
make_informed_decision("allow", "foobar")
def test_make_informed_decision_with_invalid_policy_as_keyword_argument():
with pytest.raises(ValueError):
make_informed_decision(data="allow", policy="foobar")
if __name__ == "__main__":
pytest.main([__file__])
目前,除了第三个测试之外,所有测试都通过了,因为第一个位置参数 'allow' 被解释为 policy,而不是应有的 data。
如何调整 validate_policy 装饰器以使所有测试都通过?
【问题讨论】:
-
使策略成为必需的关键字参数。显式优于隐式。
-
Rick Teachey,这似乎是个好主意,除了我的代码库是在 Python 2 中,所以 PEP 3102 还没有实现。我认为这就是您将
policy设为必需的关键字参数的意思? -
无赖.........
标签: python wrapper python-decorators