В чем разница между enum и namedtuple?
Я хотел бы знать, каковы различия между enum и namedtuple и когда следует использовать один над другим.
2 ответов
в качестве аналогии (хотя и несовершенной) вы можете подумать о enum.Enum
и namedtuple
в python как enum
и struct
В C. другими словами,enum
s-это способ сглаживания значений, в то время как namedtuple
- это способ инкапсуляции данных по имени. Два не являются взаимозаменяемыми, и вы можете использовать enum
s как именованные значения в 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)
вы можете получить доступ к именованным "атрибутами" человека так же, как и обычный предмет.
>>> print(bert.name)
Bert
>>> print(bert.age)
5
>>> print(bert.hair_color)
HairColor.black
>>> print(bert.hair_color.value)
3
вы часто не видим namedtuple
S, как это, потому что то же самое может быть достигнуто с помощью более широко известных class
декларации. The class
определение ниже ведет себя почти идентично namedtuple
выше определение.
class Person:
def __init__(self, name, age, hair_color):
self.name = name
self.age = age
self.hair_color = hair_color
однако, основное различие между namedtuple
и class
объект является то, что атрибуты namedtuple
невозможно изменить после его создания.
на namedtuple это быстро структуры, которые с помощью __слот__ вместо _ _ dict__, завершает контент, который вы предоставляете при инициализации (который практически становится только для чтения, Хотя существует метод _replace ()).
namedtuple обычно используется, когда вам нужно много (например, сотни, тысячи и даже миллионы) объектов одного типа или Вы читаете и/или пишете запись.
Например, часто приводимый пример-это точка namedtuple, которая может использоваться для работы с вершиной многоугольника с ее x, y, z
компоненты.
накладные расходы, введенные namedtuple над обычным кортежем, минимальны по сравнению с преимуществом всегда указывать на правильный компонент по имени (.икс. ,год. ,Зет. ,..) вместо индекса (0, 1, 2, ...).
Чтение кода, такого как A. x, проще, чем a[0]: значение очевидно, даже через несколько месяцев после написания кода и, лучше для других программистов.
таким образом, namedtuple быстр, может использоваться для значимой идентификации содержимого кортежа и, наконец, может сосуществовать со старым кодом, обращающимся к содержимому кортежа по индексу.
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()
переходя от примера выше, как только все обращается к компонентам точек по имени, а не по индексу, дальнейшие изменения могут быть более легко введены, не входя в изменение любого индекса номер:
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()
An перечисление - это способ связать символические имена с постоянными значениями и классифицировать их как определенный набор. Мы определяем перечисление, создавая класс, производный от любого перечисление или IntEnum, в зависимости от значений, которые мы хотим, чтобы наши константы имели: 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
в pythonic development-перечисления элементы могут иметь определенное значение, которое может быть уникальным или нет, в зависимости от ваших предпочтений и спецификаций. The уникальный декоратор используется для обеспечения уникальности значений. По умолчанию можно присвоить одно и то же постоянное значение двум или более различным символам имена.
class Color_4(IntEnum):
red = 1
green = 2
blue = 3
RED = 1
GREEN = 2
BLUE = 3
перечисления элементы могут быть сравнены друг с другом, но для того, чтобы они были успешными, не только должно совпадать значение, даже их тип должен быть одинаковым.
например:
Color_4.red == Color_4.RED
вернет True (тот же класс, то же значение), но следующее:
Shape.SQUARE == tuple('square')
будет False-потому что правый элемент сравнения-кортеж ('square') - не имеет формы типа, хотя оба они имеют одинаковый значение.
в заключение, перечисления и namedtuples являются различными инструментами.
перечисления были добавлены совсем недавно в Python (поиск PEP435). Если мне не изменяет память, namedtuples были доступны довольно долго, но я все еще новичок в сообществе, поэтому я могу ошибаться. HTH