What is the pythonic way to enforce a function to take a specific set of values for a given parameter? For instance there is a function like:
def results(status, data):
I want to restrict the parameter status
to a set of values like 0, 1 or 99.
The special syntax *args in function definitions in python is used to pass a variable number of arguments to a function. It is used to pass a non-key worded, variable-length argument list. The syntax is to use the symbol * to take in a variable number of arguments; by convention, it is often used with the word args.
5 Types of Arguments in Python Function Definition: positional arguments. arbitrary positional arguments. arbitrary keyword arguments.
However, in Python 3, there is a simple way to enforce it! By adding a * in the function arguments, we force all succeeding arguments to be named. E.g. by having the first argument be * , we force all arguments to be named. This makes writing defensive Python easier!
The best practice for implementing name-value arguments in your functions is by defining them in an arguments block.
Any number of arguments can have a default value. But you must make sure to not have a non-default argument after a default argument. In other words, if you provide a default argument, all others succeeding it must have default values as well. The reason is simple. Imagine you have a function with two parameters.
Function argument validation can declare four kinds of arguments. Functions can define any of these kinds of arguments, but the arguments must be defined in the following order: Positional arguments must be passed to a function in a specific order.
Sometimes, we do not know in advance the number of arguments that will be passed into a function. Python allows us to handle this kind of situation through function calls with an arbitrary number of arguments. In the function definition, we use an asterisk (*) before the parameter name to denote this kind of argument.
You need to check the value inside the function:
def results(status, data):
valid = {0, 1, 99}
if status not in valid:
raise ValueError("results: status must be one of %r." % valid)
Here, valid
is a set, because the only thing we care about is whether status
is a member of the collection (we aren't interested in order, for example). To avoid recreating the set each time you use the function, you'd probably define it as a "constant"1 global:
VALID_STATUS = {0, 1, 99}
def results(status, data):
if status not in VALID_STATUS:
raise ValueError("results: status must be one of %r." % VALID_STATUS)
Example usage:
>>> results(7, [...])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in results
ValueError: results: status must be one of {0, 1, 99}.
Always try to raise the most appropriate exception you can - ValueError
tells the caller of the function what's going on better than Exception
does, for example.
1 It's not really constant, but by convention, ALL_UPPERCASE
variable names in Python are considered to be intended as constants.
You can check within the function itself if status
is a valid value and if it is not then raise an exception.
def results(status,data):
list_valid_status = [0, 1, 99]
# list_valid_status = (0, 1, 99) # could be a tuple so it doesn't get modified by accident
if status not in list_valid_status:
raise ValueError("Wrong status")
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With