enum和namedtuple有什么区别?

Car*_*nso 20 python enums namedtuple python-3.x

我想知道enum和namedtuple之间有什么区别,以及何时应该使用一个而不是另一个.

Bil*_*lly 24

作为一个类比(虽然是一个不完美的),你可以想象enum.Enumnamedtuple在python中enumstruct在C中.换句话说,enums是一种别名值namedtuple的方式,而是一种按名称封装数据的方式.这两个不是真的可以互换,你可以使用enums作为a中的命名值namedtuple.

我认为这个例子说明了不同之处.

from collections import namedtuple
from enum import Enum

class HairColor(Enum):
    blonde = 1
    brown = 2
    black = 3
    red = 4

Person = namedtuple('Person', ['name','age','hair_color'])
bert = Person('Bert', 5, HairColor.black)
Run Code Online (Sandbox Code Playgroud)

您可以像访问常规对象一样访问人员的命名"属性".

>>> print(bert.name)
Bert
>>> print(bert.age)
5
>>> print(bert.hair_color)
HairColor.black
>>> print(bert.hair_color.value)
3
Run Code Online (Sandbox Code Playgroud)

你经常看不到namedtuple这样的东西,因为使用更广为人知的class宣言可以实现同样的基本概念.以下class定义与namedtuple上面的定义几乎完全相同.

class Person:
    def __init__(self, name, age, hair_color):
        self.name = name
        self.age = age
        self.hair_color = hair_color
Run Code Online (Sandbox Code Playgroud)

但是,a namedtupleclass对象之间的主要区别在于a 的属性namedtuple在创建后不能更改.

  • 你也可以使用`namedtuple`s作为枚举的值...`class People(enum.Enum):john = Person('John',21,HairColor.blonde)` (2认同)

Alb*_*ena 13

namedtuple是一个快速的是,使用结构__slots__代替__dict__,最终确定在初始化您提供的内容(即几乎成为只读,虽然_replace()方法存在).

当您需要许多(例如数百,数千甚至数百万)相同类型的对象或者您正在阅读和/或写入记录时,通常会使用命名元组.
例如,一个经常被引用的例子是Point namedtuple,它可能用于处理带有x, y, z组件的多边形顶点.
如果与总是通过名称(.x,.y,.z,...)而不是索引(0,1,2 )指向正确的组件的好处相比,由一个常规元组引入的一个命名元组的开销是最小的.,...).
读取Ax之类的代码比A [0]更容易:意思很明显,即使你编写代码几个月后也是如此,对于其他程序员来说也是如此.

因此,命名元组很快,可以用于有意义地识别元组的内容,并且最后但并非最不重要的是,可以与通过索引访问元组内容的旧代码共存.

from collections import namedtuple

Point = namedtuple('Point', 'x y z')  # note the x, y, z fields

origin = Point(0, 0, 0)

A = Point(1, 1, 1)
B = Point(1, 1, 0)
C = Point(1, 0, 0)
D = Point(1, 2, 3)

for p in (origin, A, B, C, D):
    print(p)
    print('x:', p.x, '  y:', p.y, '  z:', p.z)
    print('x:', p[0], '  y:', p[1], '  z:', p[2])
    print()
Run Code Online (Sandbox Code Playgroud)

从上面的例子开始,只要一切都按名称而不是索引访问点组件,通过不更改任何索引号,可能更容易引入进一步的更改:

from collections import namedtuple


Point = namedtuple('Point', 'name x y z')  # addition of the field 'name'

origin = Point('O', 0, 0, 0)

A = Point('A', 1, 1, 1)
B = Point('B', 1, 1, 0)
C = Point('C', 1, 0, 0)
D = Point('D', 1, 0, 1)

for p in (origin, A, B, C, D):
    print(p)
    print(p.name)  # more readable than p[0] that is no more the x coordinate
    print('x:', p.x,  '  y:', p.y,  '  z:', p.z)  # unchanged
    print('x:', p[1], '  y:', p[2], '  z:', p[3])  # changed
    print()
Run Code Online (Sandbox Code Playgroud)

一个枚举是一种方法,几个符号的名称为恒定值,并将其归类为特定的一组.我们通过创建从EnumIntEnum派生的类来定义枚举,具体取决于我们希望常量具有的值:Enum是泛型版本,IntEnum强制执行每个常量值都是int类型的事实.

例如,枚举适用于按名称,特定整数类型,性别定义颜色,或者更常见地 - 属于特定集合的元素.

from enum import Enum, IntEnum, unique

class Color_1(Enum):
    red = 'red'
    green = 'green'
    blue = 'blue'

class Color_2(Enum):
    red = (255, 0, 0)
    green = (0, 255, 0)
    blue = (0, 0, 255)

class Color_3(IntEnum):
    red = 0xFF0000
    green = 0xFF00
    blue = 0xFF

class Gender_1(Enum):
    unknown = 'U'
    male = 'M'
    female = 'F'

class Gender_2(Enum):
    unknown = 0.3
    male = 0.5
    female = 0.7

class Shape(Enum):  # Note the different constants types, perfectly legal
    TRIANGLE = 't'
    RECTANGLE = 5
    SQUARE = tuple('square')

class DataType(IntEnum):
    int8 = -8
    int16 = -16
    int32 = -32
    int64 = -64
    int = -2
    negative = -1
    positive = 1
    uint = 2
    uint8 = 8
    uint16 = 16
    uint32 = 32
    uint64 = 64
Run Code Online (Sandbox Code Playgroud)

在pythonic开发中 - 枚举元素可能具有指定的特定值 - 可以是唯一的也可以不是,具体取决于您的偏好和规范.该独特的装饰用于强制值的唯一性.默认情况下,可以将相同的常量值分配给两个或多个不同的符号名称.

class Color_4(IntEnum):
    red = 1
    green = 2
    blue = 3
    RED = 1
    GREEN = 2
    BLUE = 3
Run Code Online (Sandbox Code Playgroud)

枚举元素可以相互比较,但要使它们成功,不仅值必须匹配,即使它们的类型必须相同.

例如:

Color_4.red == Color_4.RED
Run Code Online (Sandbox Code Playgroud)

将返回True(相同的类,相同的值),但以下内容:

Shape.SQUARE == tuple('square')
Run Code Online (Sandbox Code Playgroud)

将是False - 因为比较的正确元素 - 元组('square') - 不是Shape类型,尽管它们都具有相同的值.

总之,枚举和命名元组是不同的工具.

最近在Python中添加了枚举(搜索PEP435).如果记忆能让我正确,那么命名元组可以使用很长时间,但我仍然是社区新手,因此我可能错了.HTH