且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

如何在enums上放置docstrings?

更新时间:2023-12-05 19:13:10

是的,这是我最喜欢的食谱。作为一个奖励,也不必指定整数值。以下是一个例子:

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

您可能会问为什么我不只是NSEW NE NW SE SW的价值是?因为当我得到它的repr看到< AddressSegment.ordinal:'NSEW NE NW SE SW'> 有点笨重,但是在docstring中容易获得这些信息一个很好的妥协。



以下是枚举的配方:

  AutoEnum(enum.Enum)类:

自动从1开始枚举枚举成员

包括对每个成员的自定义docstring的支持

$
__last_number__ = 0

def __new __(cls,* args):
忽略参数(将在__init__中处理。 $ b value = cls .__ last_number__ + 1
cls .__ last_number__ = value
obj = object .__ new __(cls)
obj._value_ = value
return obj

def __init __(self,* args):
可以处理0或1个参数;更多需要自定义__init__

0 =自动编号w / o docstring
1 =自动编号w / docs tring
2+ =需要自定义__init__


如果len(args)== 1和isinstance(args [0],(str,unicode)):
self .__ doc__ = args [0]
elif args:
raise TypeError('%s not处理 - 需要自定义__init__'%(args,))
$我在$ $ c $ _ $ _ pre $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ c> __ new __
是要使子类化 AutoEnum 更容易我想进一步扩展。

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 pretty much all python objects do, I would like to set them. Is there an easy way to do that?

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.

    """
    __last_number__ = 0

    def __new__(cls, *args):
        """Ignores arguments (will be handled in __init__."""
        value = cls.__last_number__ + 1
        cls.__last_number__ = value
        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,))

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.