Ich schreibe mehrere Funktionen, die ein Argument namens policy
akzeptieren, das nur bestimmte Werte haben darf (nämlich 'allow'
oder 'deny'
). Wenn nicht, möchte ich eine ValueError
ausgelöst werden.Wie definiere ich in Python einen Funktions-Wrapper, der ein Argument mit einem bestimmten Namen validiert?
Der Kürze halber möchte ich einen Dekorateur dafür definieren. Bisher habe ich mit folgendem kommen:
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
Das Problem ist, dass dies nur funktioniert, wenn policy
das erste Positions Argument der Funktion ist. Ich möchte jedoch zulassen, dass policy
an jeder Position erscheint.
Um genau zu sein, sind hier einige (Dummy) Funktionen make_decision
und make_informed_decision
genannt, die ein Argument policy
an verschiedenen Positionen annehmen, und einige Testfälle mit ihnen zu gehen:
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__])
Derzeit werden alle Tests bestanden außer der dritte, weil das erste Positionsargument 'allow'
eher als policy
interpretiert wird als als data
, wie es sein sollte.
Wie kann ich den validate_policy
Dekorateur so anpassen, dass alle Tests bestanden werden?
Machen Sie die Richtlinie zu einem erforderlichen Schlüsselwortargument. Explizit ist besser als implizit. –
[Rick Teachey] (http://stackoverflow.com/users/2437514/rick-teachey), das scheint eine gute Idee zu sein, außer dass meine Code-Basis in Python 2 ist, also [PEP 3102] (http: // legacy .python.org/dev/peps/pep-3102 /) wurde nicht implementiert. Ich nehme an, dass Sie damit gemeint sind, indem Sie "Richtlinie" zu einem erforderlichen Keyword-Argument machen? –
Bummer ......... –