5

I have a function that has a few possible return values. As a trivial example, let's imagine it took in a positive int and returned "small", "medium", or "large":

def size(x):
    if x < 10:
        return SMALL
    if x < 20:
        return MEDIUM
    return LARGE

I am wondering the best way to write & define the return values. I am wondering about using Python function attributes, as follows:

def size(x):
    if x < 10:
        return size.small
    if x < 20:
        return size.medium
    return size.large

size.small = 1
size.medium = 2
size.large = 3

Then my calling code would look like:

if size(n) == size.small:
    ...

This seems like a nice built-in "enum", possibly clearer/simpler than creating a module-level enum, or defining the 3 values as global constants like SIZE_SMALL, SIZE_MEDIUM, etc. But I don't think I've seen code like this before. Is this a good approach or are there pitfalls/drawbacks?

RexE
  • 17,085
  • 16
  • 58
  • 81
  • Why not use a class ? then you can return class variables that can be used from outside the class. It is a bit more oop. – jramirez Oct 29 '13 at 23:58
  • @wim: I don't see anything there about function attributes. That's just a question about enums in general. I'm asking about a specific technique for implementing an enum-type structure. – RexE Oct 29 '13 at 23:59
  • These are normally defined as module/global vars because knowledge is required to be at the module/global level, ie somewhere else in your code settings.small = var – tk. Oct 30 '13 at 00:03
  • @tk, valid point, but the function `size` itself is not private, so its attributes are also accessible at a module/global level. – RexE Oct 30 '13 at 00:07
  • Therefore if the knowledge of the values belongs strictly to the function your way is correct, however if there is ambiguity I would consider placing it elsewhere. – tk. Oct 30 '13 at 00:13

2 Answers2

3

While you can, I wouldn't, especially now that Python has an Enum type in 3.4 which has been backported.

Your example above might look like this as an Enum:

class Size(Enum):

    small = 1
    medium = 2
    large = 3

    @classmethod
    def classify(cls, number):
        if number < 10:
            return cls.small
        elif number < 20:
            return cls.medium
        else:
            return cls.large

In use:

--> Size.classify(15)
<Size.medium: 2>
Ethan Furman
  • 63,992
  • 20
  • 159
  • 237
1

namedtuple, perhaps?

>>> from collections import namedtuple
>>> 
>>> SizeSpec = namedtuple('SizeSpec', ['small', 'medium', 'large'])
>>> 
>>> size = SizeSpec(small=1, medium=2, large=3)
>>> 
>>> size.small
1
>>> size.medium
2
>>> size.large
3
arshajii
  • 127,459
  • 24
  • 238
  • 287