enforce arguments to a specific list of values

Question:

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.

Asked By: user3885927

||

Answers:

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")
Answered By: jramirez

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.

Answered By: Zero Piraeus

An alternative option would be to go with Enums for instance

from enum import IntEnum

class STATUSES(IntEnum):
    ZERO = 0
    ONE = 1
    OTHER = 99

def results(status, data):
    status = STATUS(status)

calling STATUS(status) would raise ValueError similar to other answers, but with this approach you have some benefits:

  1. Putting type annotation status:STATUSES would make it easier for others to get set of valid fields (especially when working with IDE)
  2. You can name STATUSES in human-readable format (don’t have a broader context of this particular use case)
Answered By: Vvitek
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.