在Python
3.4中,我们在标准库中获得了一个Enum库:enum
。我们可以在pypi中使用enum34的enum
Python
2.4到2.7(甚至3.1到3.3)使用它的反向端口。
但是我们已经设法在没有这个新模块的情况下相处了很长时间-那么为什么现在有了它呢?
我对其他语言的枚举的用途有一个大致的了解。在Python中,通常使用如下所示的裸类并将其称为枚举:
class Colors:
blue = 1
green = 2
red = 3
可以在API中使用它来创建值的规范表示,例如:
function_of_color(Colors.green)
如果有任何批评,它是可变的,您不能(轻松)遍历它,我们如何知道整数的语义2
?
然后我想我可以使用诸如namedtuple之类的东西,这将是不可变的吗?
>>> Colors = namedtuple('Colors', 'blue green red')
>>> colors = Colors('blue', 'green', 'red')
>>> colors
Colors(blue='blue', green='green', red='red')
>>> list(colors)
['blue', 'green', 'red']
>>> len(colors)
3
>>> colors.blue
'blue'
>>> colors.index(colors.blue)
0
namedtuple的创建有点多余(我们必须为每个名称写两次),所以有点不雅致。获取颜色的“数字”也不太好(我们必须写colors
两次)。值检查必须使用字符串来完成,这会降低效率。
回到枚举。
枚举的目的是什么?他们为语言创造了什么价值?什么时候应该使用它们,什么时候应该避免使用它们?
枚举的目的是什么?他们为语言创造了什么价值?什么时候应该使用它们,什么时候应该避免使用它们?
Enum类型通过PEP 435进入Python 。给出的理由是:
枚举的属性可用于定义一组不变的,相关的常数值,这些常数值可能具有也可能没有语义。
当为此目的使用数字和字符串时,它们可以被表征为“魔术数字”或“魔术字符串”。数字很少带有语义,字符串很容易混淆(大写,拼写,蛇形或驼峰式大写?)
星期几和学校字母成绩是这种价值集合的例子。
这是docs中的示例:
from enum import Enum
class Color(Enum):
red = 1
green = 2
blue = 3
像裸类一样,这比namedtuple示例更具可读性和优雅性,它也是不可变的,并且还有其他好处,如下所述。
>>> type(Color.red)
<enum 'Color'>
>>> isinstance(Color.green, Color)
True
这使您可以在Enum定义中的成员上定义功能。可以使用其他现有方法来完成在值上定义功能的操作,但这将非常麻烦。
字符串表示形式是人类可读的,而repr具有更多信息:
>>> print(Color.red)
Color.red
>>> print(repr(Color.red))
<Color.red: 1>
我发现这是对魔术数字的改进,甚至可能比namedtuple中的字符串更好。
枚举也支持迭代(类似于namedtuple,但不支持裸类):
>>> for color in Color:
print(color)
Color.red
Color.green
Color.blue
该__members__
属性是枚举名称到它们各自的枚举对象的有序映射(类似于namedtuple的_asdict()
函数)。
>>> Color.__members__
mappingproxy(OrderedDict([('red', <Color.red: 1>), ('green', <Color.green: 2>),
('blue', <Color.blue: 3>)]))
您可以序列化和反序列化枚举(以防有人担心):
>>> import pickle
>>> color.red is pickle.loads(pickle.dumps(color.red))
True
这是光秃秃的类所没有的一个不错的功能,并且很难分辨出别名在其中namedtuple
。
class Color(Enum):
red = 1
green = 2
blue = 3
really_blue = 3
别名在规范名称之后,但它们都相同:
>>> Color.blue is Color.really_blue
True
如果应禁止使用别名以避免值冲突,请使用enum.unique
装饰器(严格的主导功能)。
is
枚举旨在使用进行测试is
,这是在过程中快速检查单个对象的身份。
>>> Color.red is Color.red
True
>>> Color.red is Color.blue
False
>>> Color.red is not Color.blue
True
相等性测试也可以,但是与身份的测试is
是最佳的。
枚举类具有与常规Python类型不同的语义。Enum的值是Enum的实例,并且是这些值在内存中的单例-实例化它们没有其他目的。
>>> Color.red is Color('red')
要记住这一点很重要,也许是不利的一面,但是在这个方面进行比较就是将苹果与橙子进行比较。
虽然Enum类知道创建成员的顺序,但不假定枚举是有序的。这是一个功能,因为可能被枚举的许多事物没有自然顺序,因此顺序将是任意的。
但是,您可以给您的枚举顺序(请参阅下一节)。
您不能使用声明了成员的Enum子类化,但 可以
将未声明成员共享行为的Enum子类化(请参阅docs中的OrderedEnum配方)。
这是一个功能-用成员将Enum子类化几乎没有意义,但同样,比较是苹果和橘子。
enum.Enum
什么时候应该使用?这是Python中新的规范枚举。协作者会期望您的枚举的行为像这些枚举。
在代码中有规范的枚举数据源的任何地方都可以使用它,在此处要显式指定使用规范名称而不是任意数据。
例如,如果在你的代码,你希望用户状态,它不是"Green"
,"green"
,2,或"Greene"
,但Color.green
-使用enum.Enum对象。它既明确又具体。
文档中有很多示例和配方。
停止自己动手或让人们猜测魔术数字和字符串。不要回避它们。拥抱他们。
但是,如果出于历史原因要求您的枚举成员必须为整数,则IntEnum
来自同一模块的枚举成员具有相同的行为,但是它也是整数,因为它int
在子类化之前先将内建子类化Enum
。来自IntEnum
的帮助:
class IntEnum(builtins.int, Enum)
我们可以看到IntEnum值将作为的实例进行测试int
。
本文向大家介绍什么是MySQL ENUM数据类型?使用ENUM数据类型有什么优势?,包括了什么是MySQL ENUM数据类型?使用ENUM数据类型有什么优势?的使用技巧和注意事项,需要的朋友参考一下 与标准数据类型不同,ENUM数据类型是1到65,535个字符串的枚举列表,指示字段的允许值。定义ENUM时,您将创建一个项目列表,必须从中选择该值(或者可以为NULL)。 例如,如果希望字段包含“ A
问题内容: 我正在尝试在一个抽象类中创建一个抽象方法,该抽象类将自己的Enum作为参数。但是我也希望枚举是通用的。 所以我这样宣布: 在实现中,我列举了一个枚举: 并且方法声明变为: 但是,如果我这样做: 我无法访问并显示错误消息: 我做了这样的解决方法: 但是我想知道是否有可能无法通过我的解决方法? 问题答案: 在您的方法实现中,不是枚举,而是类型参数(通常称为)。因此,它掩盖了与已经说过的ax
创建枚举 import enum class BugStatus(enum.Enum): new = 7 incomplete = 6 invalid = 5 wont_fix = 4 in_progress = 3 fix_committed = 2 fix_released = 1 print('\nMember name: {}'.
Rust的枚举是代数数据类型。据我所知,这似乎包含了struct是什么。struct有什么不同之处需要保留它?
本文向大家介绍MySQL ENUM数据类型的不同属性是什么?,包括了MySQL ENUM数据类型的不同属性是什么?的使用技巧和注意事项,需要的朋友参考一下 可以使用以下影响允许值的属性来定义MySQL ENUM类型- NOT NULL- 在ENUM类型中,默认情况下允许NULL值。要禁止NULL值,我们需要在描述ENUM列时使用NOT NULL属性。 NULL -NULL属性是DEFAULT
问题内容: 我一直在看该类的源代码。对我来说,这似乎是一个普通的抽象类,带有受保护的构造函数。它不是最终的,它内部没有任何特殊的注释,并且不使用本机代码。但是,它不能直接子类化。实际上,以下代码无法编译: 我知道这是Java中的一个特殊类,并且我知道有充分的理由应禁止直接子类化。但是从技术上讲,您如何执行此行为?程序员是否可以创建类似的非最终类,尽管具有可访问的构造函数,该类仍不允许直接子类化?