Search code examples
pythonclassdictionarypython-decoratorspython-2.6

Defining a list of values within a class


I know that this is a simple question, but I don't know what this is called and I can't find any details online...

Using Python 2.6, I simply want to be able to reference some predefined values that are defined in a class. I want the user to be able to reference them when using the class, as well as use these values within the class when validating parameters passed into functions of the class.

In my example, there are four different severity levels allowed. Currently, the user needs to use Issue.severity_levels["critical"] to retrieve the correct value for a critical issue. I would like them to be able to use Issue.severity_levels.critical instead. I also want to be able to use if severity not in severity_levels: to validate the severity parameter passed to a function.

My example:

class Issue:

    severity_levels = {"critical": "critical", "info": "info", "warning": "warning",
                       "error": "error"}

    @classmethod
    def page_out(description, ticket, details, severity="critical", custom=None):

        # Normalize severity
        severity = severity.lower()

        # Stop with error on a bad severity level
        if severity not in severity_levels:
            raise ValueError("Invalid severity")

        # do stuff...

What is this called? How do I implement it in Python 2.6? (Yes, that is very old, but that is the current environment we are working in. It is being replaced, but the new system is not ready yet.)


Solution

  • This can be done with a combination of namedtuple (according to the internet, this was introduced with Python 2.6), and class attributes (as far as I know, also available).

    namedtuple works like a combination of a tuple and a dictionary (and also like a mini class). You can access elements by name using the dot notation, and also check for inclusion like you could with a regular tuple. You can even index them.

    from collections import namedtuple
    
    # Define the namedtuple
    Levels = namedtuple('Levels', ['critical', 'info', 'warning', 'error'])
    
    
    class Issue:
    
        # Create the class attribute, an instance of the namedtuple defined above
        severity_levels = Levels('critical', 'info', 'warning', 'error') #=  {"critical": "critical", "info": "info", "warning": "warning", "error": "error"}
        
        @classmethod
        def page_out(description, ticket, details, severity="critical", custom=None):
    
            # Normalize severity
            severity = severity.lower()
            
            # Stop with error on a bad severity level
            if severity not in severity_levels:
                raise ValueError("Invalid severity")
    
    
    'critical' in Issue.severity_levels  # True
    
    'new' in Issue.severity_levels   # False
    
    Issue.severity_levels.info   # 'info'
    
    Issue.severity_levels[0]   # 'critical'
    

    Addendum

    To get the 'key' from the 'value' is a bit more convoluted:

    # using a list comprehension (I think this works in 2.6)
    [k for k, v in Issue.severity_levels._asdict().items() if v == 'error']
    
    # using a for loop
    for k, v in Issue.severity_levels._asdict().items():
        if v == 'error':
            print(k)