Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the difference between enum and namedtuple?

I would like to know what are the differences between enum and namedtuple and when one should use one over the other.

like image 370
Carlos Afonso Avatar asked Nov 16 '16 12:11

Carlos Afonso


People also ask

When should I use Namedtuple?

In general, you can use namedtuple instances wherever you need a tuple-like object. Named tuples have the advantage that they provide a way to access their values using field names and the dot notation. This will make your code more Pythonic.

What is difference between Namedtuple and tuple?

Tuples are immutable, whether named or not. namedtuple only makes the access more convenient, by using names instead of indices. You can only use valid identifiers for namedtuple , it doesn't perform any hashing — it generates a new type instead.

What is the difference between Namedtuple and dictionary?

Python Namedtuple vs Dict – Difference explainedPython namedtuples are immutable while a dictionary is mutable in python. A namedtuple can be used to access elements in the tuple using the names and not just the indexes while the data in a python dict can be accessed using a key:value pairing.

What type is a Namedtuple?

Python namedtuple is an immutable container type, whose values can be accessed with indexes and named attributes. It has functionality like tuples with additional features. A named tuple is created with the collections. namedtuple factory function.


2 Answers

As an analogy (albeit an imperfect one), you can think of enum.Enum and namedtuple in python as enum and struct in C. In other words, enums are a way of aliasing values, while namedtuple is a way of encapsulating data by name. The two are not really interchangeable, and you can use enums as the named values in a namedtuple.

I think this example illustrates the difference.

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) 

You can access the named "attributes" of the person the same way you would a regular object.

>>> print(bert.name) Bert >>> print(bert.age) 5 >>> print(bert.hair_color) HairColor.black >>> print(bert.hair_color.value) 3 

You often don't see namedtuples like this because the same essential concept can be accomplished by using the more widely known class declaration. The class definition below behaves almost identically to the namedtuple definition above.

class Person:     def __init__(self, name, age, hair_color):         self.name = name         self.age = age         self.hair_color = hair_color 

However, a major difference between a namedtuple and a class object is that the attributes of a namedtuple cannot be changed after its creation.

like image 83
Billy Avatar answered Sep 23 '22 21:09

Billy


The namedtuple is a fast structure that, using __slots__ instead of __dict__, finalizes the content you provide at initialization (that practically becomes read only, though a _replace() method exists).

A namedtuple is generally used when you need many (such as hundreds, thousands and even millions of) objects of the same type or you are reading and/or writing a record.
For instance, an often cited example is a Point namedtuple that might be used to work with a polygon vertex with its x, y, z components.
The overhead introduced by a namedtuple over a regular tuple is minimal if compared to the benefit of always pointing to the right component by name (.x, .y, .z, ...) instead of by index (0, 1, 2, ...).
Reading code such as A.x is easier than A[0]: the meaning is evident, even months after you have written the code and, better, for other programmers as well.

Thus a namedtuple is fast, can be used to meaningfully identify the content of the tuple and, last but not least, may coexist with older code accessing a tuple content by index.

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() 

Going on from the example above, as soon as everything is accessing the points components by name instead of by index, further changes might be more easily introduced, by not going into changing any index number:

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 enumeration is a way to couple symbolic names to constant values and classify them as a specific set. We define an enumeration by creating a class derived from either Enum or IntEnum, depending on the values we want our constants to have: Enum is the generic version, IntEnum enforces the fact that every constant value will be of type int.

For instance, enums are good for defining colors by name, specific integer types, gender, or, again, - more generally - elements belonging to a specific set.

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 

In the pythonic development - enumerations elements may have a specific value assigned - that can be either unique or not, depending on your preference and specification. The unique decorator is used to enforce values uniqueness. By default, it is possible to assign the same constant value to two or more different symbolic names.

class Color_4(IntEnum):     red = 1     green = 2     blue = 3     RED = 1     GREEN = 2     BLUE = 3 

Enumerations elements can be compared with each other, but for them to be successful, not only must the value match, even their type must be the same.

For instance:

Color_4.red == Color_4.RED 

will return True (same class, same value), but the following:

Shape.SQUARE == tuple('square') 

will be False - because the right element of the comparison - tuple('square') - is not of type Shape, though both of them have the same value.

To conclude, enums and namedtuples are different instruments.

Enumerations have been added just recently to Python (search PEP435). If memory serves me right, namedtuples were available for quite a long time, but I am still a community newbie, thus I may be wrong. HTH

like image 42
Alberto Vassena Avatar answered Sep 23 '22 21:09

Alberto Vassena