How do I put docstrings on Enums?

前端 未结 2 1212
春和景丽
春和景丽 2020-12-09 16:58

Python 3.4 has a new enum module and Enum data type. If you are unable to switch to 3.4 yet, Enum has been backported.

Since Enum members support docstrings, as pre

相关标签:
2条回答
  • 2020-12-09 17:41

    Yes there is, and it's my favorite recipe so far. As a bonus, one does not have to specify the integer value either. Here's an example:

    class AddressSegment(AutoEnum):
        misc = "not currently tracked"
        ordinal = "N S E W NE NW SE SW"
        secondary = "apt bldg floor etc"
        street = "st ave blvd etc"
    

    You might ask why I don't just have "N S E W NE NW SE SW" be the value of ordinal? Because when I get its repr seeing <AddressSegment.ordinal: 'N S E W NE NW SE SW'> gets a bit clunky, but having that information readily available in the docstring is a good compromise.

    Here's the recipe for the Enum:

    class AutoEnum(enum.Enum):
        """
        Automatically numbers enum members starting from 1.
    
        Includes support for a custom docstring per member.
        """
        #
        def __new__(cls, *args):
            """Ignores arguments (will be handled in __init__."""
            value = len(cls) + 1
            obj = object.__new__(cls)
            obj._value_ = value
            return obj
        #
        def __init__(self, *args):
            """Can handle 0 or 1 argument; more requires a custom __init__.
    
            0  = auto-number w/o docstring
            1  = auto-number w/ docstring
            2+ = needs custom __init__
    
            """
            if len(args) == 1 and isinstance(args[0], (str, unicode)):
                self.__doc__ = args[0]
            elif args:
                raise TypeError('%s not dealt with -- need custom __init__' % (args,))
    

    And in use:

    >>> list(AddressSegment)
    [<AddressSegment.ordinal: 1>, <AddressSegment.secondary: 2>, <AddressSegment.misc: 3>, <AddressSegment.street: 4>]
    
    >>> AddressSegment.secondary
    <AddressSegment.secondary: 2>
    
    >>> AddressSegment.secondary.__doc__
    'apt bldg floor etc'
    

    The reason I handle the arguments in __init__ instead of in __new__ is to make subclassing AutoEnum easier should I want to extend it further.

    0 讨论(0)
  • 2020-12-09 17:55

    Functions and classes have docstrings, but most objects don't and do not even need them at all. There is no native docstring syntax for instance attributes, as they can be described exhaustively in the classes' docstring, which is also what I recommend you to do. Instances of classes normally also don't have their own docstrings, and enum members are nothing more than that.

    Sure enough you could add a docstring to almost anything. Actually you can, indeed, add anything to almost anything, as this is the way python was designed. But it is neither useful nor clean, and even what @Ethan Furman posted seems like way to much overhead just for adding a docstring to a static property.

    Long story short, even though you might not like it at first: Just don't do it and go with your enum's docstring. It is more than enough to explain the meaning of its members.

    0 讨论(0)
提交回复
热议问题