Cara menggunakan python json to namedtuple

Python’s module provides a factory function called , which is specially designed to make your code more Pythonic when you’re working with tuples. With

>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
5, you can create sequence types that allow you to access their values using descriptive field names and the dot notation instead of unclear integer indices.

If you have some experience using Python, then you know that writing Pythonic code is a core skill for Python developers. In this tutorial, you’ll level up that skill using

>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
7.

In this tutorial, you’ll learn how to:

  • Create
    >>> from collections import namedtuple
    
    >>> Point = namedtuple["Point", ["x", "_y"]]
    Traceback [most recent call last]:
      ...
    ValueError: Field names cannot start with an underscore: '_y'
    
    7 classes using
    >>> from collections import namedtuple
    
    >>> Point = namedtuple["Point", ["x", "_y"]]
    Traceback [most recent call last]:
      ...
    ValueError: Field names cannot start with an underscore: '_y'
    
    5
  • Identify and take advantage of cool features of
    >>> from collections import namedtuple
    
    >>> Point = namedtuple["Point", ["x", "_y"]]
    Traceback [most recent call last]:
      ...
    ValueError: Field names cannot start with an underscore: '_y'
    
    7
  • Use
    >>> from collections import namedtuple
    
    >>> Point = namedtuple["Point", ["x", "_y"]]
    Traceback [most recent call last]:
      ...
    ValueError: Field names cannot start with an underscore: '_y'
    
    7 instances to write Pythonic code
  • Decide whether to use a
    >>> from collections import namedtuple
    
    >>> Point = namedtuple["Point", ["x", "_y"]]
    Traceback [most recent call last]:
      ...
    ValueError: Field names cannot start with an underscore: '_y'
    
    7 or a similar data structure
  • Subclass a
    >>> from collections import namedtuple
    
    >>> Point = namedtuple["Point", ["x", "_y"]]
    Traceback [most recent call last]:
      ...
    ValueError: Field names cannot start with an underscore: '_y'
    
    7 to provide new features

To get the most out of this tutorial, you need to have a general understanding of Python’s philosophy related to writing Pythonic and readable code. You also need to know the basics of working with:

  • Tuples
  • Dictionaries
  • Classes and object-oriented programming
  • Data classes
  • Type hints

If you don’t have all the required knowledge before starting this tutorial, then that’s okay! You can stop and review the above resources as needed.

Free Bonus: Click here to get a Python Cheat Sheet and learn the basics of Python 3, like working with data types, dictionaries, lists, and Python functions.

Using
>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
7 to Write Pythonic Code

Python’s is a factory function available in . It allows you to create

>>> from collections import namedtuple

>>> Point1 = namedtuple["Point", "x y"]
>>> Point1


>>> class Point:
...     def __init__[self, x, y]:
...         self.x = x
...         self.y = y
...

>>> Point2 = Point
>>> Point2

7 subclasses with named fields. You can access the values in a given named tuple using the dot notation and the field names, like in
>>> from collections import namedtuple

>>> Point1 = namedtuple["Point", "x y"]
>>> Point1


>>> class Point:
...     def __init__[self, x, y]:
...         self.x = x
...         self.y = y
...

>>> Point2 = Point
>>> Point2

8.

Python’s

>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
7 was created to improve code readability by providing a way to access values using descriptive field names instead of integer indices, which most of the time don’t provide any context on what the values are. This feature also makes the code cleaner and more maintainable.

In contrast, using indices to values in a regular tuple can be annoying, difficult to read, and error-prone. This is especially true if the tuple has a lot of fields and is constructed far away from where you’re using it.

Note: In this tutorial, you’ll find different terms used to refer to Python’s

>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
7, its factory function, and its instances.

To avoid confusion, here’s a summary of how each term is used throughout the tutorial:

TermMeaning

>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
5The factory function
>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
7,
>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
7 classThe tuple subclass returned by
>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
5
>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
7 instance, named tupleAn instance of a specific
>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
7 class

You’ll find these terms used with their corresponding meaning throughout the tutorial.

Besides this main feature of named tuples, you’ll find out that they:

  • Are immutable data structures
  • Have a consistent value
  • Can work as dictionary keys
  • Can be stored in sets
  • Have a helpful docstring based on the type and field names
  • Provide a helpful string representation that prints the tuple content in a
    >>> from collections import namedtuple
    
    >>> Point = namedtuple["Point", "x y"]
    
    >>> Point[x=2, y=4]
    Point[x=2, y=4]
    
    >>> Point[**{"x": 4, "y": 8}]
    Point[x=4, y=8]
    
    7 format
  • Support indexing
  • Provide additional methods and attributes, such as , , , and so on
  • Are backward compatible with regular tuples
  • Have similar memory consumption to regular tuples

In general, you can use

>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
7 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.

With this brief introduction to

>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
7 and its general features, you can dive deeper into creating and using them in your code.

Remove ads

Creating Tuple-Like Classes With
>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
5

You use a

>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
5 to create an and tuple-like data structure with field names. A popular example that you’ll find in tutorials about
>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
7 is to create a class to represent a mathematical point.

Depending on the problem, you probably want to use an immutable data structure to represent a given point. Here’s how you can create a two-dimensional point using a regular tuple:

>>>

>>> # Create a 2D point as a tuple
>>> point = [2, 4]
>>> point
[2, 4]

>>> # Access coordinate x
>>> point[0]
2
>>> # Access coordinate y
>>> point[1]
4

>>> # Try to update a coordinate value
>>> point[0] = 3
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: 'tuple' object does not support item assignment

Here, you create an immutable two-dimensional

# passenger.py

from collections import namedtuple

from database import get_column_names

Passenger = namedtuple["Passenger", get_column_names[]]
6 using a regular
>>> from collections import namedtuple

>>> Point1 = namedtuple["Point", "x y"]
>>> Point1


>>> class Point:
...     def __init__[self, x, y]:
...         self.x = x
...         self.y = y
...

>>> Point2 = Point
>>> Point2

7. This code works: You have a
# passenger.py

from collections import namedtuple

from database import get_column_names

Passenger = namedtuple["Passenger", get_column_names[]]
6 with two coordinates, and you can’t modify any of those coordinates. However, is this code readable? Can you tell up front what the
# passenger.py

from collections import namedtuple

from database import get_column_names

Passenger = namedtuple["Passenger", get_column_names[]]
9 and
Traceback [most recent call last]:
  ...
ValueError: Type names and field names cannot be a keyword: 'class'
0 indices mean? To prevent these ambiguities, you can use a
>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
7 like this:

>>>

>>> from collections import namedtuple

>>> # Create a namedtuple type, Point
>>> Point = namedtuple["Point", "x y"]
>>> issubclass[Point, tuple]
True

>>> # Instantiate the new type
>>> point = Point[2, 4]
>>> point
Point[x=2, y=4]

>>> # Dot notation to access coordinates
>>> point.x
2
>>> point.y
4

>>> # Indexing to access coordinates
>>> point[0]
2
>>> point[1]
4

>>> # Named tuples are immutable
>>> point.x = 100
Traceback [most recent call last]:
  File "", line 1, in 
AttributeError: can't set attribute

Now you have a

# passenger.py

from collections import namedtuple

from database import get_column_names

Passenger = namedtuple["Passenger", get_column_names[]]
6 with two appropriately named fields,
Traceback [most recent call last]:
  ...
ValueError: Type names and field names cannot be a keyword: 'class'
3 and
Traceback [most recent call last]:
  ...
ValueError: Type names and field names cannot be a keyword: 'class'
4. Your
# passenger.py

from collections import namedtuple

from database import get_column_names

Passenger = namedtuple["Passenger", get_column_names[]]
6 provides a user-friendly and descriptive string representation [
Traceback [most recent call last]:
  ...
ValueError: Type names and field names cannot be a keyword: 'class'
6] by default. It allows you to access the coordinates using the dot notation, which is convenient, readable, and explicit. You can also use indices to access the value of each coordinate.

Note: It’s important to note that, while tuples and named tuples are immutable, the values they store don’t necessarily have to be immutable.

It’s totally legal to create a tuple or a named tuple that holds mutable values:

>>>

>>> from collections import namedtuple

>>> Person = namedtuple["Person", "name children"]
>>> john = Person["John Doe", ["Timmy", "Jimmy"]]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy']]
>>> id[john.children]
139695902374144

>>> john.children.append["Tina"]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy', 'Tina']]
>>> id[john.children]
139695902374144

>>> hash[john]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unhashable type: 'list'

You can create named tuples that contain mutable objects. You can modify the mutable objects in the underlying tuple. However, this doesn’t mean that you’re modifying the tuple itself. The tuple will continue holding the same memory references.

Finally, tuples or named tuples with mutable values aren’t , as you saw in the above example.

Finally, since

>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
7 classes are subclasses of
>>> from collections import namedtuple

>>> Point1 = namedtuple["Point", "x y"]
>>> Point1


>>> class Point:
...     def __init__[self, x, y]:
...         self.x = x
...         self.y = y
...

>>> Point2 = Point
>>> Point2

7, they’re immutable as well. So if you try to change a value of a coordinate, then you’ll get an
Traceback [most recent call last]:
  ...
ValueError: Type names and field names cannot be a keyword: 'class'
9.

Providing Required Arguments to
>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
5

As you learned before,

>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
5 is a factory function rather than a typical data structure. To create a new
>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
7, you need to provide two positional arguments to the function:

  1. >>> from collections import namedtuple
    
    >>> # Create a namedtuple type, Point
    >>> Point = namedtuple["Point", "x y"]
    >>> issubclass[Point, tuple]
    True
    
    >>> # Instantiate the new type
    >>> point = Point[2, 4]
    >>> point
    Point[x=2, y=4]
    
    >>> # Dot notation to access coordinates
    >>> point.x
    2
    >>> point.y
    4
    
    >>> # Indexing to access coordinates
    >>> point[0]
    2
    >>> point[1]
    4
    
    >>> # Named tuples are immutable
    >>> point.x = 100
    Traceback [most recent call last]:
      File "", line 1, in 
    AttributeError: can't set attribute
    
    03 provides the class name for the
    >>> from collections import namedtuple
    
    >>> Point = namedtuple["Point", ["x", "_y"]]
    Traceback [most recent call last]:
      ...
    ValueError: Field names cannot start with an underscore: '_y'
    
    7 returned by
    >>> from collections import namedtuple
    
    >>> Point = namedtuple["Point", ["x", "_y"]]
    Traceback [most recent call last]:
      ...
    ValueError: Field names cannot start with an underscore: '_y'
    
    5. You need to pass a string with a to this argument.
  2. >>> from collections import namedtuple
    
    >>> # Create a namedtuple type, Point
    >>> Point = namedtuple["Point", "x y"]
    >>> issubclass[Point, tuple]
    True
    
    >>> # Instantiate the new type
    >>> point = Point[2, 4]
    >>> point
    Point[x=2, y=4]
    
    >>> # Dot notation to access coordinates
    >>> point.x
    2
    >>> point.y
    4
    
    >>> # Indexing to access coordinates
    >>> point[0]
    2
    >>> point[1]
    4
    
    >>> # Named tuples are immutable
    >>> point.x = 100
    Traceback [most recent call last]:
      File "", line 1, in 
    AttributeError: can't set attribute
    
    06 provides the field names that you’ll use to access the values in the tuple. You can provide the field names using:
    • An of strings, such as
      >>> from collections import namedtuple
      
      >>> # Create a namedtuple type, Point
      >>> Point = namedtuple["Point", "x y"]
      >>> issubclass[Point, tuple]
      True
      
      >>> # Instantiate the new type
      >>> point = Point[2, 4]
      >>> point
      Point[x=2, y=4]
      
      >>> # Dot notation to access coordinates
      >>> point.x
      2
      >>> point.y
      4
      
      >>> # Indexing to access coordinates
      >>> point[0]
      2
      >>> point[1]
      4
      
      >>> # Named tuples are immutable
      >>> point.x = 100
      Traceback [most recent call last]:
        File "", line 1, in 
      AttributeError: can't set attribute
      
      07
    • A string with each field name separated by whitespace, such as
      >>> from collections import namedtuple
      
      >>> # Create a namedtuple type, Point
      >>> Point = namedtuple["Point", "x y"]
      >>> issubclass[Point, tuple]
      True
      
      >>> # Instantiate the new type
      >>> point = Point[2, 4]
      >>> point
      Point[x=2, y=4]
      
      >>> # Dot notation to access coordinates
      >>> point.x
      2
      >>> point.y
      4
      
      >>> # Indexing to access coordinates
      >>> point[0]
      2
      >>> point[1]
      4
      
      >>> # Named tuples are immutable
      >>> point.x = 100
      Traceback [most recent call last]:
        File "", line 1, in 
      AttributeError: can't set attribute
      
      08
    • A string with each field name separated by commas, such as
      >>> from collections import namedtuple
      
      >>> # Create a namedtuple type, Point
      >>> Point = namedtuple["Point", "x y"]
      >>> issubclass[Point, tuple]
      True
      
      >>> # Instantiate the new type
      >>> point = Point[2, 4]
      >>> point
      Point[x=2, y=4]
      
      >>> # Dot notation to access coordinates
      >>> point.x
      2
      >>> point.y
      4
      
      >>> # Indexing to access coordinates
      >>> point[0]
      2
      >>> point[1]
      4
      
      >>> # Named tuples are immutable
      >>> point.x = 100
      Traceback [most recent call last]:
        File "", line 1, in 
      AttributeError: can't set attribute
      
      09

To illustrate how to provide

>>> from collections import namedtuple

>>> # Create a namedtuple type, Point
>>> Point = namedtuple["Point", "x y"]
>>> issubclass[Point, tuple]
True

>>> # Instantiate the new type
>>> point = Point[2, 4]
>>> point
Point[x=2, y=4]

>>> # Dot notation to access coordinates
>>> point.x
2
>>> point.y
4

>>> # Indexing to access coordinates
>>> point[0]
2
>>> point[1]
4

>>> # Named tuples are immutable
>>> point.x = 100
Traceback [most recent call last]:
  File "", line 1, in 
AttributeError: can't set attribute
06, here are different ways to create points:

>>>

>>> from collections import namedtuple

>>> # A list of strings for the field names
>>> Point = namedtuple["Point", ["x", "y"]]
>>> Point

>>> Point[2, 4]
Point[x=2, y=4]

>>> # A string with comma-separated field names
>>> Point = namedtuple["Point", "x, y"]
>>> Point

>>> Point[4, 8]
Point[x=4, y=8]

>>> # A generator expression for the field names
>>> Point = namedtuple["Point", [field for field in "xy"]]
>>> Point

>>> Point[8, 16]
Point[x=8, y=16]

In these examples, you first create

>>> from collections import namedtuple

>>> # Create a namedtuple type, Point
>>> Point = namedtuple["Point", "x y"]
>>> issubclass[Point, tuple]
True

>>> # Instantiate the new type
>>> point = Point[2, 4]
>>> point
Point[x=2, y=4]

>>> # Dot notation to access coordinates
>>> point.x
2
>>> point.y
4

>>> # Indexing to access coordinates
>>> point[0]
2
>>> point[1]
4

>>> # Named tuples are immutable
>>> point.x = 100
Traceback [most recent call last]:
  File "", line 1, in 
AttributeError: can't set attribute
11 using a
>>> from collections import namedtuple

>>> # Create a namedtuple type, Point
>>> Point = namedtuple["Point", "x y"]
>>> issubclass[Point, tuple]
True

>>> # Instantiate the new type
>>> point = Point[2, 4]
>>> point
Point[x=2, y=4]

>>> # Dot notation to access coordinates
>>> point.x
2
>>> point.y
4

>>> # Indexing to access coordinates
>>> point[0]
2
>>> point[1]
4

>>> # Named tuples are immutable
>>> point.x = 100
Traceback [most recent call last]:
  File "", line 1, in 
AttributeError: can't set attribute
12 of field names. Then you use a string with comma-separated field names. Finally, you use a generator expression. This last option might look like overkill in this example. However, it’s intended to illustrate the flexibility of the process.

Note: If you use an iterable to provide the field names, then you should use a sequence-like iterable because the order of the fields is important to produce reliable results.

Using a

>>> from collections import namedtuple

>>> # Create a namedtuple type, Point
>>> Point = namedtuple["Point", "x y"]
>>> issubclass[Point, tuple]
True

>>> # Instantiate the new type
>>> point = Point[2, 4]
>>> point
Point[x=2, y=4]

>>> # Dot notation to access coordinates
>>> point.x
2
>>> point.y
4

>>> # Indexing to access coordinates
>>> point[0]
2
>>> point[1]
4

>>> # Named tuples are immutable
>>> point.x = 100
Traceback [most recent call last]:
  File "", line 1, in 
AttributeError: can't set attribute
13, for example, would work but could produce unexpected results:

>>>

>>> from collections import namedtuple

>>> Point = namedtuple["Point", {"x", "y"}]
>>> Point[2, 4]
Point[y=2, x=4]

When you use an unordered iterable to provide the fields to a

>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
7, you can get unexpected results. In the above example, the coordinate names are swapped, which might not be right for your use case.

You can use any valid Python identifier for the field names, except for:

  • Names starting with an underscore [
    >>> from collections import namedtuple
    
    >>> # Create a namedtuple type, Point
    >>> Point = namedtuple["Point", "x y"]
    >>> issubclass[Point, tuple]
    True
    
    >>> # Instantiate the new type
    >>> point = Point[2, 4]
    >>> point
    Point[x=2, y=4]
    
    >>> # Dot notation to access coordinates
    >>> point.x
    2
    >>> point.y
    4
    
    >>> # Indexing to access coordinates
    >>> point[0]
    2
    >>> point[1]
    4
    
    >>> # Named tuples are immutable
    >>> point.x = 100
    Traceback [most recent call last]:
      File "", line 1, in 
    AttributeError: can't set attribute
    
    15]
  • Python
    >>> from collections import namedtuple
    
    >>> # Create a namedtuple type, Point
    >>> Point = namedtuple["Point", "x y"]
    >>> issubclass[Point, tuple]
    True
    
    >>> # Instantiate the new type
    >>> point = Point[2, 4]
    >>> point
    Point[x=2, y=4]
    
    >>> # Dot notation to access coordinates
    >>> point.x
    2
    >>> point.y
    4
    
    >>> # Indexing to access coordinates
    >>> point[0]
    2
    >>> point[1]
    4
    
    >>> # Named tuples are immutable
    >>> point.x = 100
    Traceback [most recent call last]:
      File "", line 1, in 
    AttributeError: can't set attribute
    
    16

If you provide field names that violate either of these conditions, then you get a

>>> from collections import namedtuple

>>> # Create a namedtuple type, Point
>>> Point = namedtuple["Point", "x y"]
>>> issubclass[Point, tuple]
True

>>> # Instantiate the new type
>>> point = Point[2, 4]
>>> point
Point[x=2, y=4]

>>> # Dot notation to access coordinates
>>> point.x
2
>>> point.y
4

>>> # Indexing to access coordinates
>>> point[0]
2
>>> point[1]
4

>>> # Named tuples are immutable
>>> point.x = 100
Traceback [most recent call last]:
  File "", line 1, in 
AttributeError: can't set attribute
17:

>>>

>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'

In this example, the second field name starts with and underscore, so you get a

>>> from collections import namedtuple

>>> # Create a namedtuple type, Point
>>> Point = namedtuple["Point", "x y"]
>>> issubclass[Point, tuple]
True

>>> # Instantiate the new type
>>> point = Point[2, 4]
>>> point
Point[x=2, y=4]

>>> # Dot notation to access coordinates
>>> point.x
2
>>> point.y
4

>>> # Indexing to access coordinates
>>> point[0]
2
>>> point[1]
4

>>> # Named tuples are immutable
>>> point.x = 100
Traceback [most recent call last]:
  File "", line 1, in 
AttributeError: can't set attribute
17 telling you that field names can’t start with that character. This is intended to avoid name conflicts with the
>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
7 methods and attributes.

In the case of

>>> from collections import namedtuple

>>> # Create a namedtuple type, Point
>>> Point = namedtuple["Point", "x y"]
>>> issubclass[Point, tuple]
True

>>> # Instantiate the new type
>>> point = Point[2, 4]
>>> point
Point[x=2, y=4]

>>> # Dot notation to access coordinates
>>> point.x
2
>>> point.y
4

>>> # Indexing to access coordinates
>>> point[0]
2
>>> point[1]
4

>>> # Named tuples are immutable
>>> point.x = 100
Traceback [most recent call last]:
  File "", line 1, in 
AttributeError: can't set attribute
03, a question can arise when you look at the examples above: Why do I need to provide the
>>> from collections import namedtuple

>>> # Create a namedtuple type, Point
>>> Point = namedtuple["Point", "x y"]
>>> issubclass[Point, tuple]
True

>>> # Instantiate the new type
>>> point = Point[2, 4]
>>> point
Point[x=2, y=4]

>>> # Dot notation to access coordinates
>>> point.x
2
>>> point.y
4

>>> # Indexing to access coordinates
>>> point[0]
2
>>> point[1]
4

>>> # Named tuples are immutable
>>> point.x = 100
Traceback [most recent call last]:
  File "", line 1, in 
AttributeError: can't set attribute
03 argument? The answer is that you need a name for the class returned by
>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
5. This is like creating an alias for an existing class:

>>>

>>> from collections import namedtuple

>>> Point1 = namedtuple["Point", "x y"]
>>> Point1


>>> class Point:
...     def __init__[self, x, y]:
...         self.x = x
...         self.y = y
...

>>> Point2 = Point
>>> Point2

In the first example, you create

>>> from collections import namedtuple

>>> # Create a namedtuple type, Point
>>> Point = namedtuple["Point", "x y"]
>>> issubclass[Point, tuple]
True

>>> # Instantiate the new type
>>> point = Point[2, 4]
>>> point
Point[x=2, y=4]

>>> # Dot notation to access coordinates
>>> point.x
2
>>> point.y
4

>>> # Indexing to access coordinates
>>> point[0]
2
>>> point[1]
4

>>> # Named tuples are immutable
>>> point.x = 100
Traceback [most recent call last]:
  File "", line 1, in 
AttributeError: can't set attribute
11 using
>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
5. Then you assign this new type to the variable
>>> from collections import namedtuple

>>> # Create a namedtuple type, Point
>>> Point = namedtuple["Point", "x y"]
>>> issubclass[Point, tuple]
True

>>> # Instantiate the new type
>>> point = Point[2, 4]
>>> point
Point[x=2, y=4]

>>> # Dot notation to access coordinates
>>> point.x
2
>>> point.y
4

>>> # Indexing to access coordinates
>>> point[0]
2
>>> point[1]
4

>>> # Named tuples are immutable
>>> point.x = 100
Traceback [most recent call last]:
  File "", line 1, in 
AttributeError: can't set attribute
25. In the second example, you create a regular Python class also named
>>> from collections import namedtuple

>>> # Create a namedtuple type, Point
>>> Point = namedtuple["Point", "x y"]
>>> issubclass[Point, tuple]
True

>>> # Instantiate the new type
>>> point = Point[2, 4]
>>> point
Point[x=2, y=4]

>>> # Dot notation to access coordinates
>>> point.x
2
>>> point.y
4

>>> # Indexing to access coordinates
>>> point[0]
2
>>> point[1]
4

>>> # Named tuples are immutable
>>> point.x = 100
Traceback [most recent call last]:
  File "", line 1, in 
AttributeError: can't set attribute
11, and then you assign the class to
>>> from collections import namedtuple

>>> # Create a namedtuple type, Point
>>> Point = namedtuple["Point", "x y"]
>>> issubclass[Point, tuple]
True

>>> # Instantiate the new type
>>> point = Point[2, 4]
>>> point
Point[x=2, y=4]

>>> # Dot notation to access coordinates
>>> point.x
2
>>> point.y
4

>>> # Indexing to access coordinates
>>> point[0]
2
>>> point[1]
4

>>> # Named tuples are immutable
>>> point.x = 100
Traceback [most recent call last]:
  File "", line 1, in 
AttributeError: can't set attribute
27. In both cases, the class name is
>>> from collections import namedtuple

>>> # Create a namedtuple type, Point
>>> Point = namedtuple["Point", "x y"]
>>> issubclass[Point, tuple]
True

>>> # Instantiate the new type
>>> point = Point[2, 4]
>>> point
Point[x=2, y=4]

>>> # Dot notation to access coordinates
>>> point.x
2
>>> point.y
4

>>> # Indexing to access coordinates
>>> point[0]
2
>>> point[1]
4

>>> # Named tuples are immutable
>>> point.x = 100
Traceback [most recent call last]:
  File "", line 1, in 
AttributeError: can't set attribute
11.
>>> from collections import namedtuple

>>> # Create a namedtuple type, Point
>>> Point = namedtuple["Point", "x y"]
>>> issubclass[Point, tuple]
True

>>> # Instantiate the new type
>>> point = Point[2, 4]
>>> point
Point[x=2, y=4]

>>> # Dot notation to access coordinates
>>> point.x
2
>>> point.y
4

>>> # Indexing to access coordinates
>>> point[0]
2
>>> point[1]
4

>>> # Named tuples are immutable
>>> point.x = 100
Traceback [most recent call last]:
  File "", line 1, in 
AttributeError: can't set attribute
25 and
>>> from collections import namedtuple

>>> # Create a namedtuple type, Point
>>> Point = namedtuple["Point", "x y"]
>>> issubclass[Point, tuple]
True

>>> # Instantiate the new type
>>> point = Point[2, 4]
>>> point
Point[x=2, y=4]

>>> # Dot notation to access coordinates
>>> point.x
2
>>> point.y
4

>>> # Indexing to access coordinates
>>> point[0]
2
>>> point[1]
4

>>> # Named tuples are immutable
>>> point.x = 100
Traceback [most recent call last]:
  File "", line 1, in 
AttributeError: can't set attribute
27 are aliases for the class at hand.

Finally, you can also create a named tuple using keyword arguments or providing an existing dictionary, like this:

>>>

>>> from collections import namedtuple

>>> Point = namedtuple["Point", "x y"]

>>> Point[x=2, y=4]
Point[x=2, y=4]

>>> Point[**{"x": 4, "y": 8}]
Point[x=4, y=8]

In the first example, you use keyword arguments to create a

>>> from collections import namedtuple

>>> # Create a namedtuple type, Point
>>> Point = namedtuple["Point", "x y"]
>>> issubclass[Point, tuple]
True

>>> # Instantiate the new type
>>> point = Point[2, 4]
>>> point
Point[x=2, y=4]

>>> # Dot notation to access coordinates
>>> point.x
2
>>> point.y
4

>>> # Indexing to access coordinates
>>> point[0]
2
>>> point[1]
4

>>> # Named tuples are immutable
>>> point.x = 100
Traceback [most recent call last]:
  File "", line 1, in 
AttributeError: can't set attribute
11 object. In the second example, you use a dictionary whose keys match the fields of
>>> from collections import namedtuple

>>> # Create a namedtuple type, Point
>>> Point = namedtuple["Point", "x y"]
>>> issubclass[Point, tuple]
True

>>> # Instantiate the new type
>>> point = Point[2, 4]
>>> point
Point[x=2, y=4]

>>> # Dot notation to access coordinates
>>> point.x
2
>>> point.y
4

>>> # Indexing to access coordinates
>>> point[0]
2
>>> point[1]
4

>>> # Named tuples are immutable
>>> point.x = 100
Traceback [most recent call last]:
  File "", line 1, in 
AttributeError: can't set attribute
11. In this case, you need to perform a dictionary unpacking.

Remove ads

Using Optional Arguments With
>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
5

Besides the two required arguments, the

>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
5 factory function also takes the following optional arguments:

  • >>> from collections import namedtuple
    
    >>> # Create a namedtuple type, Point
    >>> Point = namedtuple["Point", "x y"]
    >>> issubclass[Point, tuple]
    True
    
    >>> # Instantiate the new type
    >>> point = Point[2, 4]
    >>> point
    Point[x=2, y=4]
    
    >>> # Dot notation to access coordinates
    >>> point.x
    2
    >>> point.y
    4
    
    >>> # Indexing to access coordinates
    >>> point[0]
    2
    >>> point[1]
    4
    
    >>> # Named tuples are immutable
    >>> point.x = 100
    Traceback [most recent call last]:
      File "", line 1, in 
    AttributeError: can't set attribute
    
    35
  • >>> from collections import namedtuple
    
    >>> # Create a namedtuple type, Point
    >>> Point = namedtuple["Point", "x y"]
    >>> issubclass[Point, tuple]
    True
    
    >>> # Instantiate the new type
    >>> point = Point[2, 4]
    >>> point
    Point[x=2, y=4]
    
    >>> # Dot notation to access coordinates
    >>> point.x
    2
    >>> point.y
    4
    
    >>> # Indexing to access coordinates
    >>> point[0]
    2
    >>> point[1]
    4
    
    >>> # Named tuples are immutable
    >>> point.x = 100
    Traceback [most recent call last]:
      File "", line 1, in 
    AttributeError: can't set attribute
    
    36
  • >>> from collections import namedtuple
    
    >>> # Create a namedtuple type, Point
    >>> Point = namedtuple["Point", "x y"]
    >>> issubclass[Point, tuple]
    True
    
    >>> # Instantiate the new type
    >>> point = Point[2, 4]
    >>> point
    Point[x=2, y=4]
    
    >>> # Dot notation to access coordinates
    >>> point.x
    2
    >>> point.y
    4
    
    >>> # Indexing to access coordinates
    >>> point[0]
    2
    >>> point[1]
    4
    
    >>> # Named tuples are immutable
    >>> point.x = 100
    Traceback [most recent call last]:
      File "", line 1, in 
    AttributeError: can't set attribute
    
    37

If you set

>>> from collections import namedtuple

>>> # Create a namedtuple type, Point
>>> Point = namedtuple["Point", "x y"]
>>> issubclass[Point, tuple]
True

>>> # Instantiate the new type
>>> point = Point[2, 4]
>>> point
Point[x=2, y=4]

>>> # Dot notation to access coordinates
>>> point.x
2
>>> point.y
4

>>> # Indexing to access coordinates
>>> point[0]
2
>>> point[1]
4

>>> # Named tuples are immutable
>>> point.x = 100
Traceback [most recent call last]:
  File "", line 1, in 
AttributeError: can't set attribute
35 to
>>> from collections import namedtuple

>>> # Create a namedtuple type, Point
>>> Point = namedtuple["Point", "x y"]
>>> issubclass[Point, tuple]
True

>>> # Instantiate the new type
>>> point = Point[2, 4]
>>> point
Point[x=2, y=4]

>>> # Dot notation to access coordinates
>>> point.x
2
>>> point.y
4

>>> # Indexing to access coordinates
>>> point[0]
2
>>> point[1]
4

>>> # Named tuples are immutable
>>> point.x = 100
Traceback [most recent call last]:
  File "", line 1, in 
AttributeError: can't set attribute
39, then all the invalid field names are automatically replaced with positional names.

Say your company has an old database application, written in Python, to manage the data about the passengers that travel with the company. You’re asked to update the system, and you start creating named tuples to store the data you read from the database.

The application provides a function called

>>> from collections import namedtuple

>>> # Create a namedtuple type, Point
>>> Point = namedtuple["Point", "x y"]
>>> issubclass[Point, tuple]
True

>>> # Instantiate the new type
>>> point = Point[2, 4]
>>> point
Point[x=2, y=4]

>>> # Dot notation to access coordinates
>>> point.x
2
>>> point.y
4

>>> # Indexing to access coordinates
>>> point[0]
2
>>> point[1]
4

>>> # Named tuples are immutable
>>> point.x = 100
Traceback [most recent call last]:
  File "", line 1, in 
AttributeError: can't set attribute
40 that returns a list of strings with the column names, and you think you can use that function to create a
>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
7 class. You end up with the following code:

# passenger.py

from collections import namedtuple

from database import get_column_names

Passenger = namedtuple["Passenger", get_column_names[]]

However, when you run the code, you get an exception traceback like the following:

Traceback [most recent call last]:
  ...
ValueError: Type names and field names cannot be a keyword: 'class'

This tells you that the

>>> from collections import namedtuple

>>> # Create a namedtuple type, Point
>>> Point = namedtuple["Point", "x y"]
>>> issubclass[Point, tuple]
True

>>> # Instantiate the new type
>>> point = Point[2, 4]
>>> point
Point[x=2, y=4]

>>> # Dot notation to access coordinates
>>> point.x
2
>>> point.y
4

>>> # Indexing to access coordinates
>>> point[0]
2
>>> point[1]
4

>>> # Named tuples are immutable
>>> point.x = 100
Traceback [most recent call last]:
  File "", line 1, in 
AttributeError: can't set attribute
42 column name isn’t a valid field name for your
>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
7 class. To prevent this situation, you decide to use
>>> from collections import namedtuple

>>> # Create a namedtuple type, Point
>>> Point = namedtuple["Point", "x y"]
>>> issubclass[Point, tuple]
True

>>> # Instantiate the new type
>>> point = Point[2, 4]
>>> point
Point[x=2, y=4]

>>> # Dot notation to access coordinates
>>> point.x
2
>>> point.y
4

>>> # Indexing to access coordinates
>>> point[0]
2
>>> point[1]
4

>>> # Named tuples are immutable
>>> point.x = 100
Traceback [most recent call last]:
  File "", line 1, in 
AttributeError: can't set attribute
35:

>>> from collections import namedtuple

>>> # Create a namedtuple type, Point
>>> Point = namedtuple["Point", "x y"]
>>> issubclass[Point, tuple]
True

>>> # Instantiate the new type
>>> point = Point[2, 4]
>>> point
Point[x=2, y=4]

>>> # Dot notation to access coordinates
>>> point.x
2
>>> point.y
4

>>> # Indexing to access coordinates
>>> point[0]
2
>>> point[1]
4

>>> # Named tuples are immutable
>>> point.x = 100
Traceback [most recent call last]:
  File "", line 1, in 
AttributeError: can't set attribute
0

This causes

>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
5 to automatically replace invalid names with positional names. Now suppose you retrieve one row from the database and create your first
>>> from collections import namedtuple

>>> # Create a namedtuple type, Point
>>> Point = namedtuple["Point", "x y"]
>>> issubclass[Point, tuple]
True

>>> # Instantiate the new type
>>> point = Point[2, 4]
>>> point
Point[x=2, y=4]

>>> # Dot notation to access coordinates
>>> point.x
2
>>> point.y
4

>>> # Indexing to access coordinates
>>> point[0]
2
>>> point[1]
4

>>> # Named tuples are immutable
>>> point.x = 100
Traceback [most recent call last]:
  File "", line 1, in 
AttributeError: can't set attribute
46 instance, like this:

>>>

>>> from collections import namedtuple

>>> # Create a namedtuple type, Point
>>> Point = namedtuple["Point", "x y"]
>>> issubclass[Point, tuple]
True

>>> # Instantiate the new type
>>> point = Point[2, 4]
>>> point
Point[x=2, y=4]

>>> # Dot notation to access coordinates
>>> point.x
2
>>> point.y
4

>>> # Indexing to access coordinates
>>> point[0]
2
>>> point[1]
4

>>> # Named tuples are immutable
>>> point.x = 100
Traceback [most recent call last]:
  File "", line 1, in 
AttributeError: can't set attribute
1

In this case,

>>> from collections import namedtuple

>>> # Create a namedtuple type, Point
>>> Point = namedtuple["Point", "x y"]
>>> issubclass[Point, tuple]
True

>>> # Instantiate the new type
>>> point = Point[2, 4]
>>> point
Point[x=2, y=4]

>>> # Dot notation to access coordinates
>>> point.x
2
>>> point.y
4

>>> # Indexing to access coordinates
>>> point[0]
2
>>> point[1]
4

>>> # Named tuples are immutable
>>> point.x = 100
Traceback [most recent call last]:
  File "", line 1, in 
AttributeError: can't set attribute
47 is another function available in your hypothetical application. It retrieves the data for a given passenger in a tuple. The final result is that your newly created passenger has three positional field names, and only
>>> from collections import namedtuple

>>> # Create a namedtuple type, Point
>>> Point = namedtuple["Point", "x y"]
>>> issubclass[Point, tuple]
True

>>> # Instantiate the new type
>>> point = Point[2, 4]
>>> point
Point[x=2, y=4]

>>> # Dot notation to access coordinates
>>> point.x
2
>>> point.y
4

>>> # Indexing to access coordinates
>>> point[0]
2
>>> point[1]
4

>>> # Named tuples are immutable
>>> point.x = 100
Traceback [most recent call last]:
  File "", line 1, in 
AttributeError: can't set attribute
48 reflects the original column name. When you dig into the database, you realize that the passengers table has the following columns:

ColumnStoresReplaced?Reason

>>> from collections import namedtuple

>>> # Create a namedtuple type, Point
>>> Point = namedtuple["Point", "x y"]
>>> issubclass[Point, tuple]
True

>>> # Instantiate the new type
>>> point = Point[2, 4]
>>> point
Point[x=2, y=4]

>>> # Dot notation to access coordinates
>>> point.x
2
>>> point.y
4

>>> # Indexing to access coordinates
>>> point[0]
2
>>> point[1]
4

>>> # Named tuples are immutable
>>> point.x = 100
Traceback [most recent call last]:
  File "", line 1, in 
AttributeError: can't set attribute
49A unique identifier for each passengerYesIt starts with an underscore.
>>> from collections import namedtuple

>>> # Create a namedtuple type, Point
>>> Point = namedtuple["Point", "x y"]
>>> issubclass[Point, tuple]
True

>>> # Instantiate the new type
>>> point = Point[2, 4]
>>> point
Point[x=2, y=4]

>>> # Dot notation to access coordinates
>>> point.x
2
>>> point.y
4

>>> # Indexing to access coordinates
>>> point[0]
2
>>> point[1]
4

>>> # Named tuples are immutable
>>> point.x = 100
Traceback [most recent call last]:
  File "", line 1, in 
AttributeError: can't set attribute
48A short name for each passengerNoIt’s a valid Python identifier.
>>> from collections import namedtuple

>>> # Create a namedtuple type, Point
>>> Point = namedtuple["Point", "x y"]
>>> issubclass[Point, tuple]
True

>>> # Instantiate the new type
>>> point = Point[2, 4]
>>> point
Point[x=2, y=4]

>>> # Dot notation to access coordinates
>>> point.x
2
>>> point.y
4

>>> # Indexing to access coordinates
>>> point[0]
2
>>> point[1]
4

>>> # Named tuples are immutable
>>> point.x = 100
Traceback [most recent call last]:
  File "", line 1, in 
AttributeError: can't set attribute
42The class in which the passenger travelsYesIt’s a Python keyword.
>>> from collections import namedtuple

>>> # Create a namedtuple type, Point
>>> Point = namedtuple["Point", "x y"]
>>> issubclass[Point, tuple]
True

>>> # Instantiate the new type
>>> point = Point[2, 4]
>>> point
Point[x=2, y=4]

>>> # Dot notation to access coordinates
>>> point.x
2
>>> point.y
4

>>> # Indexing to access coordinates
>>> point[0]
2
>>> point[1]
4

>>> # Named tuples are immutable
>>> point.x = 100
Traceback [most recent call last]:
  File "", line 1, in 
AttributeError: can't set attribute
48The passenger’s full nameYesIt’s repeated.

In situations where you create named tuples based on values outside your control, the

>>> from collections import namedtuple

>>> # Create a namedtuple type, Point
>>> Point = namedtuple["Point", "x y"]
>>> issubclass[Point, tuple]
True

>>> # Instantiate the new type
>>> point = Point[2, 4]
>>> point
Point[x=2, y=4]

>>> # Dot notation to access coordinates
>>> point.x
2
>>> point.y
4

>>> # Indexing to access coordinates
>>> point[0]
2
>>> point[1]
4

>>> # Named tuples are immutable
>>> point.x = 100
Traceback [most recent call last]:
  File "", line 1, in 
AttributeError: can't set attribute
35 option should be set to
>>> from collections import namedtuple

>>> # Create a namedtuple type, Point
>>> Point = namedtuple["Point", "x y"]
>>> issubclass[Point, tuple]
True

>>> # Instantiate the new type
>>> point = Point[2, 4]
>>> point
Point[x=2, y=4]

>>> # Dot notation to access coordinates
>>> point.x
2
>>> point.y
4

>>> # Indexing to access coordinates
>>> point[0]
2
>>> point[1]
4

>>> # Named tuples are immutable
>>> point.x = 100
Traceback [most recent call last]:
  File "", line 1, in 
AttributeError: can't set attribute
39 so the invalid fields get renamed with valid positional names.

The second optional argument to

>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
5 is
>>> from collections import namedtuple

>>> # Create a namedtuple type, Point
>>> Point = namedtuple["Point", "x y"]
>>> issubclass[Point, tuple]
True

>>> # Instantiate the new type
>>> point = Point[2, 4]
>>> point
Point[x=2, y=4]

>>> # Dot notation to access coordinates
>>> point.x
2
>>> point.y
4

>>> # Indexing to access coordinates
>>> point[0]
2
>>> point[1]
4

>>> # Named tuples are immutable
>>> point.x = 100
Traceback [most recent call last]:
  File "", line 1, in 
AttributeError: can't set attribute
36. This argument defaults to
>>> from collections import namedtuple

>>> # Create a namedtuple type, Point
>>> Point = namedtuple["Point", "x y"]
>>> issubclass[Point, tuple]
True

>>> # Instantiate the new type
>>> point = Point[2, 4]
>>> point
Point[x=2, y=4]

>>> # Dot notation to access coordinates
>>> point.x
2
>>> point.y
4

>>> # Indexing to access coordinates
>>> point[0]
2
>>> point[1]
4

>>> # Named tuples are immutable
>>> point.x = 100
Traceback [most recent call last]:
  File "", line 1, in 
AttributeError: can't set attribute
57, which means that the fields won’t have default values. You can set
>>> from collections import namedtuple

>>> # Create a namedtuple type, Point
>>> Point = namedtuple["Point", "x y"]
>>> issubclass[Point, tuple]
True

>>> # Instantiate the new type
>>> point = Point[2, 4]
>>> point
Point[x=2, y=4]

>>> # Dot notation to access coordinates
>>> point.x
2
>>> point.y
4

>>> # Indexing to access coordinates
>>> point[0]
2
>>> point[1]
4

>>> # Named tuples are immutable
>>> point.x = 100
Traceback [most recent call last]:
  File "", line 1, in 
AttributeError: can't set attribute
36 to an iterable of values. In this case,
>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
5 assigns the values in the
>>> from collections import namedtuple

>>> # Create a namedtuple type, Point
>>> Point = namedtuple["Point", "x y"]
>>> issubclass[Point, tuple]
True

>>> # Instantiate the new type
>>> point = Point[2, 4]
>>> point
Point[x=2, y=4]

>>> # Dot notation to access coordinates
>>> point.x
2
>>> point.y
4

>>> # Indexing to access coordinates
>>> point[0]
2
>>> point[1]
4

>>> # Named tuples are immutable
>>> point.x = 100
Traceback [most recent call last]:
  File "", line 1, in 
AttributeError: can't set attribute
36 iterable to the rightmost fields:

>>>

>>> from collections import namedtuple

>>> # Create a namedtuple type, Point
>>> Point = namedtuple["Point", "x y"]
>>> issubclass[Point, tuple]
True

>>> # Instantiate the new type
>>> point = Point[2, 4]
>>> point
Point[x=2, y=4]

>>> # Dot notation to access coordinates
>>> point.x
2
>>> point.y
4

>>> # Indexing to access coordinates
>>> point[0]
2
>>> point[1]
4

>>> # Named tuples are immutable
>>> point.x = 100
Traceback [most recent call last]:
  File "", line 1, in 
AttributeError: can't set attribute
2

In this example, the

>>> from collections import namedtuple

>>> # Create a namedtuple type, Point
>>> Point = namedtuple["Point", "x y"]
>>> issubclass[Point, tuple]
True

>>> # Instantiate the new type
>>> point = Point[2, 4]
>>> point
Point[x=2, y=4]

>>> # Dot notation to access coordinates
>>> point.x
2
>>> point.y
4

>>> # Indexing to access coordinates
>>> point[0]
2
>>> point[1]
4

>>> # Named tuples are immutable
>>> point.x = 100
Traceback [most recent call last]:
  File "", line 1, in 
AttributeError: can't set attribute
61 and
>>> from collections import namedtuple

>>> # Create a namedtuple type, Point
>>> Point = namedtuple["Point", "x y"]
>>> issubclass[Point, tuple]
True

>>> # Instantiate the new type
>>> point = Point[2, 4]
>>> point
Point[x=2, y=4]

>>> # Dot notation to access coordinates
>>> point.x
2
>>> point.y
4

>>> # Indexing to access coordinates
>>> point[0]
2
>>> point[1]
4

>>> # Named tuples are immutable
>>> point.x = 100
Traceback [most recent call last]:
  File "", line 1, in 
AttributeError: can't set attribute
62 fields have default values. This makes them optional arguments. Since you don’t define a default value for
>>> from collections import namedtuple

>>> # Create a namedtuple type, Point
>>> Point = namedtuple["Point", "x y"]
>>> issubclass[Point, tuple]
True

>>> # Instantiate the new type
>>> point = Point[2, 4]
>>> point
Point[x=2, y=4]

>>> # Dot notation to access coordinates
>>> point.x
2
>>> point.y
4

>>> # Indexing to access coordinates
>>> point[0]
2
>>> point[1]
4

>>> # Named tuples are immutable
>>> point.x = 100
Traceback [most recent call last]:
  File "", line 1, in 
AttributeError: can't set attribute
48, you need to provide a value when you create the
>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
7 instance. So, arguments without a default value are required. Note that the default values are applied to the rightmost fields.

The last argument to

>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
5 is
>>> from collections import namedtuple

>>> # Create a namedtuple type, Point
>>> Point = namedtuple["Point", "x y"]
>>> issubclass[Point, tuple]
True

>>> # Instantiate the new type
>>> point = Point[2, 4]
>>> point
Point[x=2, y=4]

>>> # Dot notation to access coordinates
>>> point.x
2
>>> point.y
4

>>> # Indexing to access coordinates
>>> point[0]
2
>>> point[1]
4

>>> # Named tuples are immutable
>>> point.x = 100
Traceback [most recent call last]:
  File "", line 1, in 
AttributeError: can't set attribute
37. If you provide a valid module name to this argument, then the
>>> from collections import namedtuple

>>> # Create a namedtuple type, Point
>>> Point = namedtuple["Point", "x y"]
>>> issubclass[Point, tuple]
True

>>> # Instantiate the new type
>>> point = Point[2, 4]
>>> point
Point[x=2, y=4]

>>> # Dot notation to access coordinates
>>> point.x
2
>>> point.y
4

>>> # Indexing to access coordinates
>>> point[0]
2
>>> point[1]
4

>>> # Named tuples are immutable
>>> point.x = 100
Traceback [most recent call last]:
  File "", line 1, in 
AttributeError: can't set attribute
67 attribute of the resulting
>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
7 is set to that value. This attribute holds the name of the module in which a given function or callable is defined:

>>>

>>> from collections import namedtuple

>>> # Create a namedtuple type, Point
>>> Point = namedtuple["Point", "x y"]
>>> issubclass[Point, tuple]
True

>>> # Instantiate the new type
>>> point = Point[2, 4]
>>> point
Point[x=2, y=4]

>>> # Dot notation to access coordinates
>>> point.x
2
>>> point.y
4

>>> # Indexing to access coordinates
>>> point[0]
2
>>> point[1]
4

>>> # Named tuples are immutable
>>> point.x = 100
Traceback [most recent call last]:
  File "", line 1, in 
AttributeError: can't set attribute
3

In this example, when you access

>>> from collections import namedtuple

>>> # Create a namedtuple type, Point
>>> Point = namedtuple["Point", "x y"]
>>> issubclass[Point, tuple]
True

>>> # Instantiate the new type
>>> point = Point[2, 4]
>>> point
Point[x=2, y=4]

>>> # Dot notation to access coordinates
>>> point.x
2
>>> point.y
4

>>> # Indexing to access coordinates
>>> point[0]
2
>>> point[1]
4

>>> # Named tuples are immutable
>>> point.x = 100
Traceback [most recent call last]:
  File "", line 1, in 
AttributeError: can't set attribute
67 on
>>> from collections import namedtuple

>>> # Create a namedtuple type, Point
>>> Point = namedtuple["Point", "x y"]
>>> issubclass[Point, tuple]
True

>>> # Instantiate the new type
>>> point = Point[2, 4]
>>> point
Point[x=2, y=4]

>>> # Dot notation to access coordinates
>>> point.x
2
>>> point.y
4

>>> # Indexing to access coordinates
>>> point[0]
2
>>> point[1]
4

>>> # Named tuples are immutable
>>> point.x = 100
Traceback [most recent call last]:
  File "", line 1, in 
AttributeError: can't set attribute
11, you get
>>> from collections import namedtuple

>>> # Create a namedtuple type, Point
>>> Point = namedtuple["Point", "x y"]
>>> issubclass[Point, tuple]
True

>>> # Instantiate the new type
>>> point = Point[2, 4]
>>> point
Point[x=2, y=4]

>>> # Dot notation to access coordinates
>>> point.x
2
>>> point.y
4

>>> # Indexing to access coordinates
>>> point[0]
2
>>> point[1]
4

>>> # Named tuples are immutable
>>> point.x = 100
Traceback [most recent call last]:
  File "", line 1, in 
AttributeError: can't set attribute
71 as a result. This indicates that your
>>> from collections import namedtuple

>>> # Create a namedtuple type, Point
>>> Point = namedtuple["Point", "x y"]
>>> issubclass[Point, tuple]
True

>>> # Instantiate the new type
>>> point = Point[2, 4]
>>> point
Point[x=2, y=4]

>>> # Dot notation to access coordinates
>>> point.x
2
>>> point.y
4

>>> # Indexing to access coordinates
>>> point[0]
2
>>> point[1]
4

>>> # Named tuples are immutable
>>> point.x = 100
Traceback [most recent call last]:
  File "", line 1, in 
AttributeError: can't set attribute
11 class is defined in your
>>> from collections import namedtuple

>>> # Create a namedtuple type, Point
>>> Point = namedtuple["Point", "x y"]
>>> issubclass[Point, tuple]
True

>>> # Instantiate the new type
>>> point = Point[2, 4]
>>> point
Point[x=2, y=4]

>>> # Dot notation to access coordinates
>>> point.x
2
>>> point.y
4

>>> # Indexing to access coordinates
>>> point[0]
2
>>> point[1]
4

>>> # Named tuples are immutable
>>> point.x = 100
Traceback [most recent call last]:
  File "", line 1, in 
AttributeError: can't set attribute
73 module.

The motivation to add the

>>> from collections import namedtuple

>>> # Create a namedtuple type, Point
>>> Point = namedtuple["Point", "x y"]
>>> issubclass[Point, tuple]
True

>>> # Instantiate the new type
>>> point = Point[2, 4]
>>> point
Point[x=2, y=4]

>>> # Dot notation to access coordinates
>>> point.x
2
>>> point.y
4

>>> # Indexing to access coordinates
>>> point[0]
2
>>> point[1]
4

>>> # Named tuples are immutable
>>> point.x = 100
Traceback [most recent call last]:
  File "", line 1, in 
AttributeError: can't set attribute
37 argument to
>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
5 in was to make it possible for named tuples to support pickling through different .

Remove ads

Exploring Additional Features of
>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
7 Classes

Besides the methods inherited from

>>> from collections import namedtuple

>>> Point1 = namedtuple["Point", "x y"]
>>> Point1


>>> class Point:
...     def __init__[self, x, y]:
...         self.x = x
...         self.y = y
...

>>> Point2 = Point
>>> Point2

7, such as
>>> from collections import namedtuple

>>> # Create a namedtuple type, Point
>>> Point = namedtuple["Point", "x y"]
>>> issubclass[Point, tuple]
True

>>> # Instantiate the new type
>>> point = Point[2, 4]
>>> point
Point[x=2, y=4]

>>> # Dot notation to access coordinates
>>> point.x
2
>>> point.y
4

>>> # Indexing to access coordinates
>>> point[0]
2
>>> point[1]
4

>>> # Named tuples are immutable
>>> point.x = 100
Traceback [most recent call last]:
  File "", line 1, in 
AttributeError: can't set attribute
78 and
>>> from collections import namedtuple

>>> # Create a namedtuple type, Point
>>> Point = namedtuple["Point", "x y"]
>>> issubclass[Point, tuple]
True

>>> # Instantiate the new type
>>> point = Point[2, 4]
>>> point
Point[x=2, y=4]

>>> # Dot notation to access coordinates
>>> point.x
2
>>> point.y
4

>>> # Indexing to access coordinates
>>> point[0]
2
>>> point[1]
4

>>> # Named tuples are immutable
>>> point.x = 100
Traceback [most recent call last]:
  File "", line 1, in 
AttributeError: can't set attribute
79,
>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
7 classes also provide three additional methods and two attributes. To prevent name conflicts with custom fields, the names of these attributes and methods start with an underscore. In this section, you’ll learn about these methods and attributes and how they work.

Creating
>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
7 Instances From Iterables

You can use to create named tuple instances. The method takes an iterable of values and returns a new named tuple:

>>>

>>> from collections import namedtuple

>>> # Create a namedtuple type, Point
>>> Point = namedtuple["Point", "x y"]
>>> issubclass[Point, tuple]
True

>>> # Instantiate the new type
>>> point = Point[2, 4]
>>> point
Point[x=2, y=4]

>>> # Dot notation to access coordinates
>>> point.x
2
>>> point.y
4

>>> # Indexing to access coordinates
>>> point[0]
2
>>> point[1]
4

>>> # Named tuples are immutable
>>> point.x = 100
Traceback [most recent call last]:
  File "", line 1, in 
AttributeError: can't set attribute
4

Here, you first create a

>>> from collections import namedtuple

>>> # Create a namedtuple type, Point
>>> Point = namedtuple["Point", "x y"]
>>> issubclass[Point, tuple]
True

>>> # Instantiate the new type
>>> point = Point[2, 4]
>>> point
Point[x=2, y=4]

>>> # Dot notation to access coordinates
>>> point.x
2
>>> point.y
4

>>> # Indexing to access coordinates
>>> point[0]
2
>>> point[1]
4

>>> # Named tuples are immutable
>>> point.x = 100
Traceback [most recent call last]:
  File "", line 1, in 
AttributeError: can't set attribute
83 class using
>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
5. Then you call
>>> from collections import namedtuple

>>> Point = namedtuple["Point", "x y"]

>>> Point[x=2, y=4]
Point[x=2, y=4]

>>> Point[**{"x": 4, "y": 8}]
Point[x=4, y=8]
8 with a list of values for each field in the
>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
7. Note that
>>> from collections import namedtuple

>>> Point = namedtuple["Point", "x y"]

>>> Point[x=2, y=4]
Point[x=2, y=4]

>>> Point[**{"x": 4, "y": 8}]
Point[x=4, y=8]
8 is a class method that works as an alternative class constructor and returns a new named tuple instance.

Finally,

>>> from collections import namedtuple

>>> Point = namedtuple["Point", "x y"]

>>> Point[x=2, y=4]
Point[x=2, y=4]

>>> Point[**{"x": 4, "y": 8}]
Point[x=4, y=8]
8 expects a single iterable as an argument, a
>>> from collections import namedtuple

>>> # Create a namedtuple type, Point
>>> Point = namedtuple["Point", "x y"]
>>> issubclass[Point, tuple]
True

>>> # Instantiate the new type
>>> point = Point[2, 4]
>>> point
Point[x=2, y=4]

>>> # Dot notation to access coordinates
>>> point.x
2
>>> point.y
4

>>> # Indexing to access coordinates
>>> point[0]
2
>>> point[1]
4

>>> # Named tuples are immutable
>>> point.x = 100
Traceback [most recent call last]:
  File "", line 1, in 
AttributeError: can't set attribute
12 in the above example. On the other hand, the
>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
7 constructor can take positional or keyword arguments, as you already learned.

Converting
>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
7 Instances Into Dictionaries

You can convert existing named tuple instances into dictionaries using . This method returns a new dictionary that uses the field names as keys. The keys of the resulting dictionary are in the same order as the fields in the original

>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
7:

>>>

>>> from collections import namedtuple

>>> # Create a namedtuple type, Point
>>> Point = namedtuple["Point", "x y"]
>>> issubclass[Point, tuple]
True

>>> # Instantiate the new type
>>> point = Point[2, 4]
>>> point
Point[x=2, y=4]

>>> # Dot notation to access coordinates
>>> point.x
2
>>> point.y
4

>>> # Indexing to access coordinates
>>> point[0]
2
>>> point[1]
4

>>> # Named tuples are immutable
>>> point.x = 100
Traceback [most recent call last]:
  File "", line 1, in 
AttributeError: can't set attribute
5

When you call

>>> from collections import namedtuple

>>> # Create a namedtuple type, Point
>>> Point = namedtuple["Point", "x y"]
>>> issubclass[Point, tuple]
True

>>> # Instantiate the new type
>>> point = Point[2, 4]
>>> point
Point[x=2, y=4]

>>> # Dot notation to access coordinates
>>> point.x
2
>>> point.y
4

>>> # Indexing to access coordinates
>>> point[0]
2
>>> point[1]
4

>>> # Named tuples are immutable
>>> point.x = 100
Traceback [most recent call last]:
  File "", line 1, in 
AttributeError: can't set attribute
92 on a named tuple, you get a new
>>> from collections import namedtuple

>>> # Create a namedtuple type, Point
>>> Point = namedtuple["Point", "x y"]
>>> issubclass[Point, tuple]
True

>>> # Instantiate the new type
>>> point = Point[2, 4]
>>> point
Point[x=2, y=4]

>>> # Dot notation to access coordinates
>>> point.x
2
>>> point.y
4

>>> # Indexing to access coordinates
>>> point[0]
2
>>> point[1]
4

>>> # Named tuples are immutable
>>> point.x = 100
Traceback [most recent call last]:
  File "", line 1, in 
AttributeError: can't set attribute
95 object that maps field names to their corresponding values in the original named tuple.

Since Python 3.8,

>>> from collections import namedtuple

>>> # Create a namedtuple type, Point
>>> Point = namedtuple["Point", "x y"]
>>> issubclass[Point, tuple]
True

>>> # Instantiate the new type
>>> point = Point[2, 4]
>>> point
Point[x=2, y=4]

>>> # Dot notation to access coordinates
>>> point.x
2
>>> point.y
4

>>> # Indexing to access coordinates
>>> point[0]
2
>>> point[1]
4

>>> # Named tuples are immutable
>>> point.x = 100
Traceback [most recent call last]:
  File "", line 1, in 
AttributeError: can't set attribute
92 has returned a regular dictionary. Before that, it returned an
>>> from collections import namedtuple

>>> # Create a namedtuple type, Point
>>> Point = namedtuple["Point", "x y"]
>>> issubclass[Point, tuple]
True

>>> # Instantiate the new type
>>> point = Point[2, 4]
>>> point
Point[x=2, y=4]

>>> # Dot notation to access coordinates
>>> point.x
2
>>> point.y
4

>>> # Indexing to access coordinates
>>> point[0]
2
>>> point[1]
4

>>> # Named tuples are immutable
>>> point.x = 100
Traceback [most recent call last]:
  File "", line 1, in 
AttributeError: can't set attribute
97 object:

>>>

>>> from collections import namedtuple

>>> # Create a namedtuple type, Point
>>> Point = namedtuple["Point", "x y"]
>>> issubclass[Point, tuple]
True

>>> # Instantiate the new type
>>> point = Point[2, 4]
>>> point
Point[x=2, y=4]

>>> # Dot notation to access coordinates
>>> point.x
2
>>> point.y
4

>>> # Indexing to access coordinates
>>> point[0]
2
>>> point[1]
4

>>> # Named tuples are immutable
>>> point.x = 100
Traceback [most recent call last]:
  File "", line 1, in 
AttributeError: can't set attribute
6

to return a regular dictionary because dictionaries remember the insertion order of their keys in Python 3.6 and up. Note that the order of keys in the resulting dictionary is equivalent to the order of fields in the original named tuple.

Replacing Fields in Existing
>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
7 Instances

The last method you’ll learn about is . This method takes keyword arguments of the form

>>> from collections import namedtuple

>>> Person = namedtuple["Person", "name children"]
>>> john = Person["John Doe", ["Timmy", "Jimmy"]]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy']]
>>> id[john.children]
139695902374144

>>> john.children.append["Tina"]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy', 'Tina']]
>>> id[john.children]
139695902374144

>>> hash[john]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unhashable type: 'list'
01 and returns a new
>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
7 instance updating the values of the selected fields:

>>>

>>> from collections import namedtuple

>>> # Create a namedtuple type, Point
>>> Point = namedtuple["Point", "x y"]
>>> issubclass[Point, tuple]
True

>>> # Instantiate the new type
>>> point = Point[2, 4]
>>> point
Point[x=2, y=4]

>>> # Dot notation to access coordinates
>>> point.x
2
>>> point.y
4

>>> # Indexing to access coordinates
>>> point[0]
2
>>> point[1]
4

>>> # Named tuples are immutable
>>> point.x = 100
Traceback [most recent call last]:
  File "", line 1, in 
AttributeError: can't set attribute
7

In this example, you update Jane’s age after her birthday. Although the name of

>>> from collections import namedtuple

>>> Person = namedtuple["Person", "name children"]
>>> john = Person["John Doe", ["Timmy", "Jimmy"]]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy']]
>>> id[john.children]
139695902374144

>>> john.children.append["Tina"]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy', 'Tina']]
>>> id[john.children]
139695902374144

>>> hash[john]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unhashable type: 'list'
00 might suggest that the method modifies the existing named tuple, that’s not what happens in practice. This is because
>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
7 instances are immutable, so
>>> from collections import namedtuple

>>> Person = namedtuple["Person", "name children"]
>>> john = Person["John Doe", ["Timmy", "Jimmy"]]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy']]
>>> id[john.children]
139695902374144

>>> john.children.append["Tina"]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy', 'Tina']]
>>> id[john.children]
139695902374144

>>> hash[john]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unhashable type: 'list'
00 doesn’t update
>>> from collections import namedtuple

>>> Person = namedtuple["Person", "name children"]
>>> john = Person["John Doe", ["Timmy", "Jimmy"]]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy']]
>>> id[john.children]
139695902374144

>>> john.children.append["Tina"]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy', 'Tina']]
>>> id[john.children]
139695902374144

>>> hash[john]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unhashable type: 'list'
06 in place.

Exploring Additional
>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
7 Attributes

Named tuples also have two additional attributes: and . The first attribute holds a tuple of strings listing the field names. The second attribute holds a dictionary that maps field names to their respective default values, if any.

In the case of

# passenger.py

from collections import namedtuple

from database import get_column_names

Passenger = namedtuple["Passenger", get_column_names[]]
0, you can use it to introspect your
>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
7 classes and instances. You can also create new classes from existing ones:

>>>

>>> from collections import namedtuple

>>> # Create a namedtuple type, Point
>>> Point = namedtuple["Point", "x y"]
>>> issubclass[Point, tuple]
True

>>> # Instantiate the new type
>>> point = Point[2, 4]
>>> point
Point[x=2, y=4]

>>> # Dot notation to access coordinates
>>> point.x
2
>>> point.y
4

>>> # Indexing to access coordinates
>>> point[0]
2
>>> point[1]
4

>>> # Named tuples are immutable
>>> point.x = 100
Traceback [most recent call last]:
  File "", line 1, in 
AttributeError: can't set attribute
8

In this example, you create a new

>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
7 called
>>> from collections import namedtuple

>>> Person = namedtuple["Person", "name children"]
>>> john = Person["John Doe", ["Timmy", "Jimmy"]]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy']]
>>> id[john.children]
139695902374144

>>> john.children.append["Tina"]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy', 'Tina']]
>>> id[john.children]
139695902374144

>>> hash[john]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unhashable type: 'list'
13 with a new field,
>>> from collections import namedtuple

>>> Person = namedtuple["Person", "name children"]
>>> john = Person["John Doe", ["Timmy", "Jimmy"]]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy']]
>>> id[john.children]
139695902374144

>>> john.children.append["Tina"]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy', 'Tina']]
>>> id[john.children]
139695902374144

>>> hash[john]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unhashable type: 'list'
14. This new type extends your old
>>> from collections import namedtuple

>>> # Create a namedtuple type, Point
>>> Point = namedtuple["Point", "x y"]
>>> issubclass[Point, tuple]
True

>>> # Instantiate the new type
>>> point = Point[2, 4]
>>> point
Point[x=2, y=4]

>>> # Dot notation to access coordinates
>>> point.x
2
>>> point.y
4

>>> # Indexing to access coordinates
>>> point[0]
2
>>> point[1]
4

>>> # Named tuples are immutable
>>> point.x = 100
Traceback [most recent call last]:
  File "", line 1, in 
AttributeError: can't set attribute
83. To do that, you access
# passenger.py

from collections import namedtuple

from database import get_column_names

Passenger = namedtuple["Passenger", get_column_names[]]
0 on
>>> from collections import namedtuple

>>> # Create a namedtuple type, Point
>>> Point = namedtuple["Point", "x y"]
>>> issubclass[Point, tuple]
True

>>> # Instantiate the new type
>>> point = Point[2, 4]
>>> point
Point[x=2, y=4]

>>> # Dot notation to access coordinates
>>> point.x
2
>>> point.y
4

>>> # Indexing to access coordinates
>>> point[0]
2
>>> point[1]
4

>>> # Named tuples are immutable
>>> point.x = 100
Traceback [most recent call last]:
  File "", line 1, in 
AttributeError: can't set attribute
83 and unpack it to a new list along with an additional field,
>>> from collections import namedtuple

>>> Person = namedtuple["Person", "name children"]
>>> john = Person["John Doe", ["Timmy", "Jimmy"]]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy']]
>>> id[john.children]
139695902374144

>>> john.children.append["Tina"]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy', 'Tina']]
>>> id[john.children]
139695902374144

>>> hash[john]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unhashable type: 'list'
14.

You can also use

# passenger.py

from collections import namedtuple

from database import get_column_names

Passenger = namedtuple["Passenger", get_column_names[]]
0 to iterate over the fields and the values in a given
>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
7 instance using Python’s
>>> from collections import namedtuple

>>> Person = namedtuple["Person", "name children"]
>>> john = Person["John Doe", ["Timmy", "Jimmy"]]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy']]
>>> id[john.children]
139695902374144

>>> john.children.append["Tina"]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy', 'Tina']]
>>> id[john.children]
139695902374144

>>> hash[john]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unhashable type: 'list'
21:

>>>

>>> from collections import namedtuple

>>> # Create a namedtuple type, Point
>>> Point = namedtuple["Point", "x y"]
>>> issubclass[Point, tuple]
True

>>> # Instantiate the new type
>>> point = Point[2, 4]
>>> point
Point[x=2, y=4]

>>> # Dot notation to access coordinates
>>> point.x
2
>>> point.y
4

>>> # Indexing to access coordinates
>>> point[0]
2
>>> point[1]
4

>>> # Named tuples are immutable
>>> point.x = 100
Traceback [most recent call last]:
  File "", line 1, in 
AttributeError: can't set attribute
9

In this example,

>>> from collections import namedtuple

>>> Person = namedtuple["Person", "name children"]
>>> john = Person["John Doe", ["Timmy", "Jimmy"]]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy']]
>>> id[john.children]
139695902374144

>>> john.children.append["Tina"]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy', 'Tina']]
>>> id[john.children]
139695902374144

>>> hash[john]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unhashable type: 'list'
21 yields tuples of the form
>>> from collections import namedtuple

>>> Person = namedtuple["Person", "name children"]
>>> john = Person["John Doe", ["Timmy", "Jimmy"]]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy']]
>>> id[john.children]
139695902374144

>>> john.children.append["Tina"]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy', 'Tina']]
>>> id[john.children]
139695902374144

>>> hash[john]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unhashable type: 'list'
23. This way, you can access both elements of the field-value pair in the underlying named tuple. Another way to iterate over fields and values at the same time could be using
>>> from collections import namedtuple

>>> Person = namedtuple["Person", "name children"]
>>> john = Person["John Doe", ["Timmy", "Jimmy"]]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy']]
>>> id[john.children]
139695902374144

>>> john.children.append["Tina"]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy', 'Tina']]
>>> id[john.children]
139695902374144

>>> hash[john]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unhashable type: 'list'
24. Go ahead and give it a try!

With

>>> from collections import namedtuple

>>> Person = namedtuple["Person", "name children"]
>>> john = Person["John Doe", ["Timmy", "Jimmy"]]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy']]
>>> id[john.children]
139695902374144

>>> john.children.append["Tina"]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy', 'Tina']]
>>> id[john.children]
139695902374144

>>> hash[john]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unhashable type: 'list'
09, you can introspect
>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
7 classes and instances to find out what fields provide default values. Having default values makes your fields optional. For example, say your
>>> from collections import namedtuple

>>> # Create a namedtuple type, Point
>>> Point = namedtuple["Point", "x y"]
>>> issubclass[Point, tuple]
True

>>> # Instantiate the new type
>>> point = Point[2, 4]
>>> point
Point[x=2, y=4]

>>> # Dot notation to access coordinates
>>> point.x
2
>>> point.y
4

>>> # Indexing to access coordinates
>>> point[0]
2
>>> point[1]
4

>>> # Named tuples are immutable
>>> point.x = 100
Traceback [most recent call last]:
  File "", line 1, in 
AttributeError: can't set attribute
83 class should include an additional field to hold the country in which the person lives. Since you’re mostly working with people from Canada, you set the appropriate default value for the
>>> from collections import namedtuple

>>> Person = namedtuple["Person", "name children"]
>>> john = Person["John Doe", ["Timmy", "Jimmy"]]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy']]
>>> id[john.children]
139695902374144

>>> john.children.append["Tina"]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy', 'Tina']]
>>> id[john.children]
139695902374144

>>> hash[john]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unhashable type: 'list'
28 field like this:

>>>

>>> from collections import namedtuple

>>> Person = namedtuple["Person", "name children"]
>>> john = Person["John Doe", ["Timmy", "Jimmy"]]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy']]
>>> id[john.children]
139695902374144

>>> john.children.append["Tina"]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy', 'Tina']]
>>> id[john.children]
139695902374144

>>> hash[john]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unhashable type: 'list'
0

With a quick query to

>>> from collections import namedtuple

>>> Person = namedtuple["Person", "name children"]
>>> john = Person["John Doe", ["Timmy", "Jimmy"]]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy']]
>>> id[john.children]
139695902374144

>>> john.children.append["Tina"]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy', 'Tina']]
>>> id[john.children]
139695902374144

>>> hash[john]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unhashable type: 'list'
09, you can figure out which fields in a given
>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
7 provide default values. In this example, any other programmer on your team can see that your
>>> from collections import namedtuple

>>> # Create a namedtuple type, Point
>>> Point = namedtuple["Point", "x y"]
>>> issubclass[Point, tuple]
True

>>> # Instantiate the new type
>>> point = Point[2, 4]
>>> point
Point[x=2, y=4]

>>> # Dot notation to access coordinates
>>> point.x
2
>>> point.y
4

>>> # Indexing to access coordinates
>>> point[0]
2
>>> point[1]
4

>>> # Named tuples are immutable
>>> point.x = 100
Traceback [most recent call last]:
  File "", line 1, in 
AttributeError: can't set attribute
83 class provides
>>> from collections import namedtuple

>>> Person = namedtuple["Person", "name children"]
>>> john = Person["John Doe", ["Timmy", "Jimmy"]]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy']]
>>> id[john.children]
139695902374144

>>> john.children.append["Tina"]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy', 'Tina']]
>>> id[john.children]
139695902374144

>>> hash[john]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unhashable type: 'list'
32 as a handy default value for
>>> from collections import namedtuple

>>> Person = namedtuple["Person", "name children"]
>>> john = Person["John Doe", ["Timmy", "Jimmy"]]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy']]
>>> id[john.children]
139695902374144

>>> john.children.append["Tina"]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy', 'Tina']]
>>> id[john.children]
139695902374144

>>> hash[john]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unhashable type: 'list'
28.

If your

>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
7 doesn’t provide default values, then
>>> from collections import namedtuple

>>> Person = namedtuple["Person", "name children"]
>>> john = Person["John Doe", ["Timmy", "Jimmy"]]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy']]
>>> id[john.children]
139695902374144

>>> john.children.append["Tina"]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy', 'Tina']]
>>> id[john.children]
139695902374144

>>> hash[john]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unhashable type: 'list'
35 holds an empty dictionary:

>>>

>>> from collections import namedtuple

>>> Person = namedtuple["Person", "name children"]
>>> john = Person["John Doe", ["Timmy", "Jimmy"]]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy']]
>>> id[john.children]
139695902374144

>>> john.children.append["Tina"]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy', 'Tina']]
>>> id[john.children]
139695902374144

>>> hash[john]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unhashable type: 'list'
1

If you don’t provide a list of default values to

>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
5, then it relies on the default value to
>>> from collections import namedtuple

>>> # Create a namedtuple type, Point
>>> Point = namedtuple["Point", "x y"]
>>> issubclass[Point, tuple]
True

>>> # Instantiate the new type
>>> point = Point[2, 4]
>>> point
Point[x=2, y=4]

>>> # Dot notation to access coordinates
>>> point.x
2
>>> point.y
4

>>> # Indexing to access coordinates
>>> point[0]
2
>>> point[1]
4

>>> # Named tuples are immutable
>>> point.x = 100
Traceback [most recent call last]:
  File "", line 1, in 
AttributeError: can't set attribute
36, which is
>>> from collections import namedtuple

>>> # Create a namedtuple type, Point
>>> Point = namedtuple["Point", "x y"]
>>> issubclass[Point, tuple]
True

>>> # Instantiate the new type
>>> point = Point[2, 4]
>>> point
Point[x=2, y=4]

>>> # Dot notation to access coordinates
>>> point.x
2
>>> point.y
4

>>> # Indexing to access coordinates
>>> point[0]
2
>>> point[1]
4

>>> # Named tuples are immutable
>>> point.x = 100
Traceback [most recent call last]:
  File "", line 1, in 
AttributeError: can't set attribute
57. In this case,
>>> from collections import namedtuple

>>> Person = namedtuple["Person", "name children"]
>>> john = Person["John Doe", ["Timmy", "Jimmy"]]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy']]
>>> id[john.children]
139695902374144

>>> john.children.append["Tina"]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy', 'Tina']]
>>> id[john.children]
139695902374144

>>> hash[john]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unhashable type: 'list'
09 holds an empty dictionary.

Remove ads

Writing Pythonic Code With
>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
7

Arguably, the fundamental use case of named tuples is to help you write more Pythonic code. The

>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
5 factory function was created to allow you to write readable, explicit, clean, and maintainable code.

In this section, you’ll write a bunch of practical examples that will help you spot good opportunities for using named tuples instead of regular tuples so you can make your code more Pythonic.

Using Field Names Instead of Indices

Say you’re creating a painting application and you need to define the pen properties to use according to the user’s choice. You’ve coded the pen’s properties in a tuple:

>>>

>>> from collections import namedtuple

>>> Person = namedtuple["Person", "name children"]
>>> john = Person["John Doe", ["Timmy", "Jimmy"]]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy']]
>>> id[john.children]
139695902374144

>>> john.children.append["Tina"]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy', 'Tina']]
>>> id[john.children]
139695902374144

>>> hash[john]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unhashable type: 'list'
2

This line of code defines a tuple with three values. Can you tell what the meaning of each value is? Maybe you can guess that the second value is related to the line style, but what’s the meaning of

>>> from collections import namedtuple

>>> Person = namedtuple["Person", "name children"]
>>> john = Person["John Doe", ["Timmy", "Jimmy"]]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy']]
>>> id[john.children]
139695902374144

>>> john.children.append["Tina"]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy', 'Tina']]
>>> id[john.children]
139695902374144

>>> hash[john]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unhashable type: 'list'
42 and
>>> from collections import namedtuple

>>> # Create a namedtuple type, Point
>>> Point = namedtuple["Point", "x y"]
>>> issubclass[Point, tuple]
True

>>> # Instantiate the new type
>>> point = Point[2, 4]
>>> point
Point[x=2, y=4]

>>> # Dot notation to access coordinates
>>> point.x
2
>>> point.y
4

>>> # Indexing to access coordinates
>>> point[0]
2
>>> point[1]
4

>>> # Named tuples are immutable
>>> point.x = 100
Traceback [most recent call last]:
  File "", line 1, in 
AttributeError: can't set attribute
39?

You could add a nice comment to provide some context for

>>> from collections import namedtuple

>>> Person = namedtuple["Person", "name children"]
>>> john = Person["John Doe", ["Timmy", "Jimmy"]]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy']]
>>> id[john.children]
139695902374144

>>> john.children.append["Tina"]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy', 'Tina']]
>>> id[john.children]
139695902374144

>>> hash[john]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unhashable type: 'list'
44, in which case you would end up with something like this:

>>>

>>> from collections import namedtuple

>>> Person = namedtuple["Person", "name children"]
>>> john = Person["John Doe", ["Timmy", "Jimmy"]]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy']]
>>> id[john.children]
139695902374144

>>> john.children.append["Tina"]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy', 'Tina']]
>>> id[john.children]
139695902374144

>>> hash[john]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unhashable type: 'list'
3

Cool! Now you know the meaning of each value in the tuple. However, what if you or another programmer is using

>>> from collections import namedtuple

>>> Person = namedtuple["Person", "name children"]
>>> john = Person["John Doe", ["Timmy", "Jimmy"]]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy']]
>>> id[john.children]
139695902374144

>>> john.children.append["Tina"]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy', 'Tina']]
>>> id[john.children]
139695902374144

>>> hash[john]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unhashable type: 'list'
44 far away from this definition? They’d have to go back to the definition just to remember what each value means.

Here’s an alternative implementation of

>>> from collections import namedtuple

>>> Person = namedtuple["Person", "name children"]
>>> john = Person["John Doe", ["Timmy", "Jimmy"]]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy']]
>>> id[john.children]
139695902374144

>>> john.children.append["Tina"]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy', 'Tina']]
>>> id[john.children]
139695902374144

>>> hash[john]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unhashable type: 'list'
44 using a
>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
7:

>>>

>>> from collections import namedtuple

>>> Person = namedtuple["Person", "name children"]
>>> john = Person["John Doe", ["Timmy", "Jimmy"]]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy']]
>>> id[john.children]
139695902374144

>>> john.children.append["Tina"]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy', 'Tina']]
>>> id[john.children]
139695902374144

>>> hash[john]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unhashable type: 'list'
4

Now your code makes it clear that

>>> from collections import namedtuple

>>> Person = namedtuple["Person", "name children"]
>>> john = Person["John Doe", ["Timmy", "Jimmy"]]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy']]
>>> id[john.children]
139695902374144

>>> john.children.append["Tina"]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy', 'Tina']]
>>> id[john.children]
139695902374144

>>> hash[john]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unhashable type: 'list'
42 represents the pen’s width,
>>> from collections import namedtuple

>>> Person = namedtuple["Person", "name children"]
>>> john = Person["John Doe", ["Timmy", "Jimmy"]]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy']]
>>> id[john.children]
139695902374144

>>> john.children.append["Tina"]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy', 'Tina']]
>>> id[john.children]
139695902374144

>>> hash[john]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unhashable type: 'list'
49 is the line style, and so on. Anyone reading your code can see and understand that. Your new implementation of
>>> from collections import namedtuple

>>> Person = namedtuple["Person", "name children"]
>>> john = Person["John Doe", ["Timmy", "Jimmy"]]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy']]
>>> id[john.children]
139695902374144

>>> john.children.append["Tina"]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy', 'Tina']]
>>> id[john.children]
139695902374144

>>> hash[john]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unhashable type: 'list'
44 has two additional lines of code. That’s a small amount of work that produces a big win in terms of readability and maintainability.

Returning Multiple Named Values From Functions

Another situation in which you can use a named tuple is when you need to from a given function. In this case, using a named tuple can make your code more readable because the returned values will also provide some context for their content.

For example, Python provides a built-in function called that takes two numbers as arguments and returns a tuple with the quotient and remainder that result from the integer division of the input numbers:

>>>

>>> from collections import namedtuple

>>> Person = namedtuple["Person", "name children"]
>>> john = Person["John Doe", ["Timmy", "Jimmy"]]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy']]
>>> id[john.children]
139695902374144

>>> john.children.append["Tina"]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy', 'Tina']]
>>> id[john.children]
139695902374144

>>> hash[john]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unhashable type: 'list'
5

To remember the meaning of each number, you might need to read the documentation of

>>> from collections import namedtuple

>>> Person = namedtuple["Person", "name children"]
>>> john = Person["John Doe", ["Timmy", "Jimmy"]]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy']]
>>> id[john.children]
139695902374144

>>> john.children.append["Tina"]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy', 'Tina']]
>>> id[john.children]
139695902374144

>>> hash[john]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unhashable type: 'list'
51 because the numbers themselves don’t provide much information on their individual meaning. The function’s name doesn’t help very much either.

Here’s a function that uses a

>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
7 to clarify the meaning of each number that
>>> from collections import namedtuple

>>> Person = namedtuple["Person", "name children"]
>>> john = Person["John Doe", ["Timmy", "Jimmy"]]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy']]
>>> id[john.children]
139695902374144

>>> john.children.append["Tina"]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy', 'Tina']]
>>> id[john.children]
139695902374144

>>> hash[john]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unhashable type: 'list'
51 returns:

>>>

>>> from collections import namedtuple

>>> Person = namedtuple["Person", "name children"]
>>> john = Person["John Doe", ["Timmy", "Jimmy"]]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy']]
>>> id[john.children]
139695902374144

>>> john.children.append["Tina"]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy', 'Tina']]
>>> id[john.children]
139695902374144

>>> hash[john]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unhashable type: 'list'
6

In this example, you add context to each returned value, so any programmer reading your code can immediately understand what each number means.

Remove ads

Reducing the Number of Arguments to Functions

Reducing the number of arguments a function can take is considered a best programming practice. This makes your function’s signature more concise and optimizes your testing process because of the reduced number of arguments and possible combinations between them.

Again, you should consider using named tuples to approach this use case. Say you’re coding an application to manage your clients’ information. The application uses a database to store clients’ data. To process the data and update the database, you’ve created several functions. One of your high-level functions is

>>> from collections import namedtuple

>>> Person = namedtuple["Person", "name children"]
>>> john = Person["John Doe", ["Timmy", "Jimmy"]]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy']]
>>> id[john.children]
139695902374144

>>> john.children.append["Tina"]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy', 'Tina']]
>>> id[john.children]
139695902374144

>>> hash[john]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unhashable type: 'list'
55, which looks like this:

>>> from collections import namedtuple

>>> Person = namedtuple["Person", "name children"]
>>> john = Person["John Doe", ["Timmy", "Jimmy"]]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy']]
>>> id[john.children]
139695902374144

>>> john.children.append["Tina"]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy', 'Tina']]
>>> id[john.children]
139695902374144

>>> hash[john]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unhashable type: 'list'
7

This function takes four arguments. The first argument,

>>> from collections import namedtuple

>>> Person = namedtuple["Person", "name children"]
>>> john = Person["John Doe", ["Timmy", "Jimmy"]]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy']]
>>> id[john.children]
139695902374144

>>> john.children.append["Tina"]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy', 'Tina']]
>>> id[john.children]
139695902374144

>>> hash[john]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unhashable type: 'list'
56, represents the database you’re working with. The rest of the arguments are closely related to a given client. This is a great opportunity to reduce the number of arguments to
>>> from collections import namedtuple

>>> Person = namedtuple["Person", "name children"]
>>> john = Person["John Doe", ["Timmy", "Jimmy"]]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy']]
>>> id[john.children]
139695902374144

>>> john.children.append["Tina"]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy', 'Tina']]
>>> id[john.children]
139695902374144

>>> hash[john]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unhashable type: 'list'
55 using a named tuple:

>>> from collections import namedtuple

>>> Person = namedtuple["Person", "name children"]
>>> john = Person["John Doe", ["Timmy", "Jimmy"]]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy']]
>>> id[john.children]
139695902374144

>>> john.children.append["Tina"]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy', 'Tina']]
>>> id[john.children]
139695902374144

>>> hash[john]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unhashable type: 'list'
8

Now

>>> from collections import namedtuple

>>> Person = namedtuple["Person", "name children"]
>>> john = Person["John Doe", ["Timmy", "Jimmy"]]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy']]
>>> id[john.children]
139695902374144

>>> john.children.append["Tina"]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy', 'Tina']]
>>> id[john.children]
139695902374144

>>> hash[john]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unhashable type: 'list'
55 takes only two arguments:
>>> from collections import namedtuple

>>> Person = namedtuple["Person", "name children"]
>>> john = Person["John Doe", ["Timmy", "Jimmy"]]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy']]
>>> id[john.children]
139695902374144

>>> john.children.append["Tina"]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy', 'Tina']]
>>> id[john.children]
139695902374144

>>> hash[john]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unhashable type: 'list'
56 and
>>> from collections import namedtuple

>>> Person = namedtuple["Person", "name children"]
>>> john = Person["John Doe", ["Timmy", "Jimmy"]]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy']]
>>> id[john.children]
139695902374144

>>> john.children.append["Tina"]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy', 'Tina']]
>>> id[john.children]
139695902374144

>>> hash[john]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unhashable type: 'list'
60. Inside the function, you use convenient and descriptive field names to provide the arguments to
>>> from collections import namedtuple

>>> Person = namedtuple["Person", "name children"]
>>> john = Person["John Doe", ["Timmy", "Jimmy"]]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy']]
>>> id[john.children]
139695902374144

>>> john.children.append["Tina"]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy', 'Tina']]
>>> id[john.children]
139695902374144

>>> hash[john]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unhashable type: 'list'
61 and
>>> from collections import namedtuple

>>> Person = namedtuple["Person", "name children"]
>>> john = Person["John Doe", ["Timmy", "Jimmy"]]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy']]
>>> id[john.children]
139695902374144

>>> john.children.append["Tina"]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy', 'Tina']]
>>> id[john.children]
139695902374144

>>> hash[john]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unhashable type: 'list'
62. Your high-level function,
>>> from collections import namedtuple

>>> Person = namedtuple["Person", "name children"]
>>> john = Person["John Doe", ["Timmy", "Jimmy"]]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy']]
>>> id[john.children]
139695902374144

>>> john.children.append["Tina"]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy', 'Tina']]
>>> id[john.children]
139695902374144

>>> hash[john]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unhashable type: 'list'
55, is more focused on the
>>> from collections import namedtuple

>>> Person = namedtuple["Person", "name children"]
>>> john = Person["John Doe", ["Timmy", "Jimmy"]]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy']]
>>> id[john.children]
139695902374144

>>> john.children.append["Tina"]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy', 'Tina']]
>>> id[john.children]
139695902374144

>>> hash[john]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unhashable type: 'list'
60. It’s also easier to test because you just need to provide two arguments to each test.

Reading Tabular Data From Files and Databases

A quite common use case for named tuples is to use them to store database records. You can define

>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
7 classes using the column names as field names and retrieve the data from the rows in the database to named tuples. You can also do something similar with CSV files.

For example, say you have a CSV file with data regarding the employees of your company, and you want to read that data into a suitable data structure for further processing. Your CSV file looks like this:

>>> from collections import namedtuple

>>> Person = namedtuple["Person", "name children"]
>>> john = Person["John Doe", ["Timmy", "Jimmy"]]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy']]
>>> id[john.children]
139695902374144

>>> john.children.append["Tina"]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy', 'Tina']]
>>> id[john.children]
139695902374144

>>> hash[john]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unhashable type: 'list'
9

You’re thinking of using Python’s and its to process the file, but you have an additional requirement—you need to store the data into an immutable and lightweight data structure. In this case, a

>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
7 might be a good choice:

>>>

>>> from collections import namedtuple

>>> # A list of strings for the field names
>>> Point = namedtuple["Point", ["x", "y"]]
>>> Point

>>> Point[2, 4]
Point[x=2, y=4]

>>> # A string with comma-separated field names
>>> Point = namedtuple["Point", "x, y"]
>>> Point

>>> Point[4, 8]
Point[x=4, y=8]

>>> # A generator expression for the field names
>>> Point = namedtuple["Point", [field for field in "xy"]]
>>> Point

>>> Point[8, 16]
Point[x=8, y=16]
0

In this example, you first open the

>>> from collections import namedtuple

>>> Person = namedtuple["Person", "name children"]
>>> john = Person["John Doe", ["Timmy", "Jimmy"]]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy']]
>>> id[john.children]
139695902374144

>>> john.children.append["Tina"]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy', 'Tina']]
>>> id[john.children]
139695902374144

>>> hash[john]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unhashable type: 'list'
69 file in a
>>> from collections import namedtuple

>>> Person = namedtuple["Person", "name children"]
>>> john = Person["John Doe", ["Timmy", "Jimmy"]]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy']]
>>> id[john.children]
139695902374144

>>> john.children.append["Tina"]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy', 'Tina']]
>>> id[john.children]
139695902374144

>>> hash[john]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unhashable type: 'list'
70 statement. Then you use to get an iterator over the lines in the CSV file. With
>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
5, you create a new
>>> from collections import namedtuple

>>> Person = namedtuple["Person", "name children"]
>>> john = Person["John Doe", ["Timmy", "Jimmy"]]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy']]
>>> id[john.children]
139695902374144

>>> john.children.append["Tina"]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy', 'Tina']]
>>> id[john.children]
139695902374144

>>> hash[john]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unhashable type: 'list'
73 class. The call to retrieves the first row of data from
>>> from collections import namedtuple

>>> Person = namedtuple["Person", "name children"]
>>> john = Person["John Doe", ["Timmy", "Jimmy"]]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy']]
>>> id[john.children]
139695902374144

>>> john.children.append["Tina"]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy', 'Tina']]
>>> id[john.children]
139695902374144

>>> hash[john]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unhashable type: 'list'
75, which contains the CSV file header. This header provides the field names for your
>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
7.

Note: When you create a

>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
7 based on field names out of your control, you should set
>>> from collections import namedtuple

>>> Person = namedtuple["Person", "name children"]
>>> john = Person["John Doe", ["Timmy", "Jimmy"]]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy']]
>>> id[john.children]
139695902374144

>>> john.children.append["Tina"]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy', 'Tina']]
>>> id[john.children]
139695902374144

>>> hash[john]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unhashable type: 'list'
78 to
>>> from collections import namedtuple

>>> # Create a namedtuple type, Point
>>> Point = namedtuple["Point", "x y"]
>>> issubclass[Point, tuple]
True

>>> # Instantiate the new type
>>> point = Point[2, 4]
>>> point
Point[x=2, y=4]

>>> # Dot notation to access coordinates
>>> point.x
2
>>> point.y
4

>>> # Indexing to access coordinates
>>> point[0]
2
>>> point[1]
4

>>> # Named tuples are immutable
>>> point.x = 100
Traceback [most recent call last]:
  File "", line 1, in 
AttributeError: can't set attribute
39. This way, you prevent issues with invalid field names, which could be a common situation when you’re working with database tables and queries, CSV files, or any other types of tabular data.

Finally, the

>>> from collections import namedtuple

>>> Person = namedtuple["Person", "name children"]
>>> john = Person["John Doe", ["Timmy", "Jimmy"]]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy']]
>>> id[john.children]
139695902374144

>>> john.children.append["Tina"]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy', 'Tina']]
>>> id[john.children]
139695902374144

>>> hash[john]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unhashable type: 'list'
80 loop creates an
>>> from collections import namedtuple

>>> Person = namedtuple["Person", "name children"]
>>> john = Person["John Doe", ["Timmy", "Jimmy"]]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy']]
>>> id[john.children]
139695902374144

>>> john.children.append["Tina"]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy', 'Tina']]
>>> id[john.children]
139695902374144

>>> hash[john]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unhashable type: 'list'
73 instance from each
>>> from collections import namedtuple

>>> Person = namedtuple["Person", "name children"]
>>> john = Person["John Doe", ["Timmy", "Jimmy"]]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy']]
>>> id[john.children]
139695902374144

>>> john.children.append["Tina"]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy', 'Tina']]
>>> id[john.children]
139695902374144

>>> hash[john]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unhashable type: 'list'
82 in the CSV file and prints the list of employees to the screen.

Using
>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
7 vs Other Data Structures

So far, you’ve learned how to create named tuples to make your code more readable, explicit, and Pythonic. You’ve also written some examples that help you spot opportunities for using named tuples in your code.

In this section, you’ll take a general look at the similarities and differences between

>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
7 classes and other Python data structures, such as dictionaries, data classes, and typed named tuples. You’ll compare named tuples with other data structures regarding the following characteristics:

  • Readability
  • Mutability
  • Memory usage
  • Performance

This way, you’ll be better prepared to choose the right data structure for your specific use case.

Remove ads

>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
7 vs Dictionary

The dictionary is a fundamental data structure in Python. The language itself is built around dictionaries, so they’re everywhere. Since they’re so common and useful, you probably use them a lot in your code. But how different are dictionaries and named tuples?

In terms of readability, you can probably say that dictionaries are as readable as named tuples. Even though they don’t provide a way to access attributes through the dot notation, the dictionary-style key lookup is quite readable and straightforward:

>>>

>>> from collections import namedtuple

>>> # A list of strings for the field names
>>> Point = namedtuple["Point", ["x", "y"]]
>>> Point

>>> Point[2, 4]
Point[x=2, y=4]

>>> # A string with comma-separated field names
>>> Point = namedtuple["Point", "x, y"]
>>> Point

>>> Point[4, 8]
Point[x=4, y=8]

>>> # A generator expression for the field names
>>> Point = namedtuple["Point", [field for field in "xy"]]
>>> Point

>>> Point[8, 16]
Point[x=8, y=16]
1

In both examples, you have a total understanding of the code and its intention. The named tuple definition requires two additional lines of code, though: one line to import the

>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
5 factory function and another to define your
>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
7 class,
>>> from collections import namedtuple

>>> # Create a namedtuple type, Point
>>> Point = namedtuple["Point", "x y"]
>>> issubclass[Point, tuple]
True

>>> # Instantiate the new type
>>> point = Point[2, 4]
>>> point
Point[x=2, y=4]

>>> # Dot notation to access coordinates
>>> point.x
2
>>> point.y
4

>>> # Indexing to access coordinates
>>> point[0]
2
>>> point[1]
4

>>> # Named tuples are immutable
>>> point.x = 100
Traceback [most recent call last]:
  File "", line 1, in 
AttributeError: can't set attribute
83.

A big difference between both data structures is that dictionaries are and named tuples are immutable. This means that you can modify dictionaries in place, but you can’t modify named tuples:

>>>

>>> from collections import namedtuple

>>> # A list of strings for the field names
>>> Point = namedtuple["Point", ["x", "y"]]
>>> Point

>>> Point[2, 4]
Point[x=2, y=4]

>>> # A string with comma-separated field names
>>> Point = namedtuple["Point", "x, y"]
>>> Point

>>> Point[4, 8]
Point[x=4, y=8]

>>> # A generator expression for the field names
>>> Point = namedtuple["Point", [field for field in "xy"]]
>>> Point

>>> Point[8, 16]
Point[x=8, y=16]
2

You can update the value of an existing key in a dictionary, but you can’t do something similar in a named tuple. You can add new key-value pairs to existing dictionaries, but you can’t add field-value pairs to existing named tuples.

Note: In named tuples, you can use

>>> from collections import namedtuple

>>> Person = namedtuple["Person", "name children"]
>>> john = Person["John Doe", ["Timmy", "Jimmy"]]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy']]
>>> id[john.children]
139695902374144

>>> john.children.append["Tina"]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy', 'Tina']]
>>> id[john.children]
139695902374144

>>> hash[john]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unhashable type: 'list'
00 to update the value of a given field, but that method creates and returns a new named tuple instance instead of updating the underlying instance in place.

In general, if you need an immutable data structure to properly solve a given problem, then consider using a named tuple instead of a dictionary so you can meet your requirements.

Regarding memory usage, named tuples are a quite lightweight data structure. Fire up your code editor or IDE and create the following script:

>>> from collections import namedtuple

>>> # A list of strings for the field names
>>> Point = namedtuple["Point", ["x", "y"]]
>>> Point

>>> Point[2, 4]
Point[x=2, y=4]

>>> # A string with comma-separated field names
>>> Point = namedtuple["Point", "x, y"]
>>> Point

>>> Point[4, 8]
Point[x=4, y=8]

>>> # A generator expression for the field names
>>> Point = namedtuple["Point", [field for field in "xy"]]
>>> Point

>>> Point[8, 16]
Point[x=8, y=16]
3

This small script uses

>>> from collections import namedtuple

>>> Person = namedtuple["Person", "name children"]
>>> john = Person["John Doe", ["Timmy", "Jimmy"]]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy']]
>>> id[john.children]
139695902374144

>>> john.children.append["Tina"]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy', 'Tina']]
>>> id[john.children]
139695902374144

>>> hash[john]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unhashable type: 'list'
90 from Pympler to get the memory footprint of a named tuple and its equivalent dictionary.

Note: Pympler is a tool to monitor and analyze the memory behavior of Python objects.

You can install it from PyPI using

>>> from collections import namedtuple

>>> Person = namedtuple["Person", "name children"]
>>> john = Person["John Doe", ["Timmy", "Jimmy"]]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy']]
>>> id[john.children]
139695902374144

>>> john.children.append["Tina"]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy', 'Tina']]
>>> id[john.children]
139695902374144

>>> hash[john]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unhashable type: 'list'
91 as usual:

>>> from collections import namedtuple

>>> # A list of strings for the field names
>>> Point = namedtuple["Point", ["x", "y"]]
>>> Point

>>> Point[2, 4]
Point[x=2, y=4]

>>> # A string with comma-separated field names
>>> Point = namedtuple["Point", "x, y"]
>>> Point

>>> Point[4, 8]
Point[x=4, y=8]

>>> # A generator expression for the field names
>>> Point = namedtuple["Point", [field for field in "xy"]]
>>> Point

>>> Point[8, 16]
Point[x=8, y=16]
4

After you run this command, Pympler will be available in your Python environment so you can run the above script.

If you run the script from your command line, then you’ll get the following output:

>>> from collections import namedtuple

>>> # A list of strings for the field names
>>> Point = namedtuple["Point", ["x", "y"]]
>>> Point

>>> Point[2, 4]
Point[x=2, y=4]

>>> # A string with comma-separated field names
>>> Point = namedtuple["Point", "x, y"]
>>> Point

>>> Point[4, 8]
Point[x=4, y=8]

>>> # A generator expression for the field names
>>> Point = namedtuple["Point", [field for field in "xy"]]
>>> Point

>>> Point[8, 16]
Point[x=8, y=16]
5

This output confirms that named tuples consume less memory than equivalent dictionaries. So if memory consumption is a restriction for you, then you should consider using a named tuple instead of a dictionary.

Note: When you compare named tuples and dictionaries, the final memory consumption difference will depend on the number of values and their types. With different values, you’ll get different results.

Finally, you need to have an idea of how different named tuples and dictionaries are in terms of operations performance. To do that, you’ll test and attribute access operations. Get back to your code editor and create the following script:

>>> from collections import namedtuple

>>> # A list of strings for the field names
>>> Point = namedtuple["Point", ["x", "y"]]
>>> Point

>>> Point[2, 4]
Point[x=2, y=4]

>>> # A string with comma-separated field names
>>> Point = namedtuple["Point", "x, y"]
>>> Point

>>> Point[4, 8]
Point[x=4, y=8]

>>> # A generator expression for the field names
>>> Point = namedtuple["Point", [field for field in "xy"]]
>>> Point

>>> Point[8, 16]
Point[x=8, y=16]
6

This script times operations common to both dictionaries and named tuples, such as membership tests and attribute access. Running the script on your current system displays an output similar to the following:

>>> from collections import namedtuple

>>> # A list of strings for the field names
>>> Point = namedtuple["Point", ["x", "y"]]
>>> Point

>>> Point[2, 4]
Point[x=2, y=4]

>>> # A string with comma-separated field names
>>> Point = namedtuple["Point", "x, y"]
>>> Point

>>> Point[4, 8]
Point[x=4, y=8]

>>> # A generator expression for the field names
>>> Point = namedtuple["Point", [field for field in "xy"]]
>>> Point

>>> Point[8, 16]
Point[x=8, y=16]
7

This output shows that operations on named tuples are slightly faster than similar operations on dictionaries.

Remove ads

>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
7 vs Data Class

Python 3.7 came with a new cool feature: data classes. According to PEP 557, data classes are similar to named tuples, but they’re mutable:

Data Classes can be thought of as “mutable namedtuples with defaults.” []

However, it’d be more accurate to say that data classes are like mutable named tuples with type hints. The “defaults” part isn’t a difference at all because named tuples can also have default values for their fields. So, at first glance, the main differences are mutability and type hints.

To create a data class, you need to import the decorator from . Then you can define your data classes using the regular class definition syntax:

>>>

>>> from collections import namedtuple

>>> # A list of strings for the field names
>>> Point = namedtuple["Point", ["x", "y"]]
>>> Point

>>> Point[2, 4]
Point[x=2, y=4]

>>> # A string with comma-separated field names
>>> Point = namedtuple["Point", "x, y"]
>>> Point

>>> Point[4, 8]
Point[x=4, y=8]

>>> # A generator expression for the field names
>>> Point = namedtuple["Point", [field for field in "xy"]]
>>> Point

>>> Point[8, 16]
Point[x=8, y=16]
8

In terms of readability, there are no significant differences between data classes and named tuples. They provide similar string representations, and you can access their attributes using the dot notation.

Mutability-wise, data classes are mutable by definition, so you can change the value of their attributes when needed. However, they have an ace up their sleeve. You can set the

>>> from collections import namedtuple

>>> Person = namedtuple["Person", "name children"]
>>> john = Person["John Doe", ["Timmy", "Jimmy"]]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy']]
>>> id[john.children]
139695902374144

>>> john.children.append["Tina"]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy', 'Tina']]
>>> id[john.children]
139695902374144

>>> hash[john]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unhashable type: 'list'
93 decorator’s
>>> from collections import namedtuple

>>> Person = namedtuple["Person", "name children"]
>>> john = Person["John Doe", ["Timmy", "Jimmy"]]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy']]
>>> id[john.children]
139695902374144

>>> john.children.append["Tina"]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy', 'Tina']]
>>> id[john.children]
139695902374144

>>> hash[john]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unhashable type: 'list'
96 argument to
>>> from collections import namedtuple

>>> # Create a namedtuple type, Point
>>> Point = namedtuple["Point", "x y"]
>>> issubclass[Point, tuple]
True

>>> # Instantiate the new type
>>> point = Point[2, 4]
>>> point
Point[x=2, y=4]

>>> # Dot notation to access coordinates
>>> point.x
2
>>> point.y
4

>>> # Indexing to access coordinates
>>> point[0]
2
>>> point[1]
4

>>> # Named tuples are immutable
>>> point.x = 100
Traceback [most recent call last]:
  File "", line 1, in 
AttributeError: can't set attribute
39 and make them immutable:

>>>

>>> from collections import namedtuple

>>> # A list of strings for the field names
>>> Point = namedtuple["Point", ["x", "y"]]
>>> Point

>>> Point[2, 4]
Point[x=2, y=4]

>>> # A string with comma-separated field names
>>> Point = namedtuple["Point", "x, y"]
>>> Point

>>> Point[4, 8]
Point[x=4, y=8]

>>> # A generator expression for the field names
>>> Point = namedtuple["Point", [field for field in "xy"]]
>>> Point

>>> Point[8, 16]
Point[x=8, y=16]
9

If you set

>>> from collections import namedtuple

>>> Person = namedtuple["Person", "name children"]
>>> john = Person["John Doe", ["Timmy", "Jimmy"]]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy']]
>>> id[john.children]
139695902374144

>>> john.children.append["Tina"]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy', 'Tina']]
>>> id[john.children]
139695902374144

>>> hash[john]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unhashable type: 'list'
96 to
>>> from collections import namedtuple

>>> # Create a namedtuple type, Point
>>> Point = namedtuple["Point", "x y"]
>>> issubclass[Point, tuple]
True

>>> # Instantiate the new type
>>> point = Point[2, 4]
>>> point
Point[x=2, y=4]

>>> # Dot notation to access coordinates
>>> point.x
2
>>> point.y
4

>>> # Indexing to access coordinates
>>> point[0]
2
>>> point[1]
4

>>> # Named tuples are immutable
>>> point.x = 100
Traceback [most recent call last]:
  File "", line 1, in 
AttributeError: can't set attribute
39 in the call to
>>> from collections import namedtuple

>>> Person = namedtuple["Person", "name children"]
>>> john = Person["John Doe", ["Timmy", "Jimmy"]]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy']]
>>> id[john.children]
139695902374144

>>> john.children.append["Tina"]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy', 'Tina']]
>>> id[john.children]
139695902374144

>>> hash[john]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unhashable type: 'list'
93, then you make the data class immutable. In this case, when you try to update Jane’s name, you get a .

Another subtle difference between named tuples and data classes is that the latter aren’t iterable by default. Stick to the Jane example and try to iterate over her data:

>>>

>>> from collections import namedtuple

>>> Point = namedtuple["Point", {"x", "y"}]
>>> Point[2, 4]
Point[y=2, x=4]
0

If you try to iterate over a bare-bones data class, then you get a

>>> from collections import namedtuple

>>> # A list of strings for the field names
>>> Point = namedtuple["Point", ["x", "y"]]
>>> Point

>>> Point[2, 4]
Point[x=2, y=4]

>>> # A string with comma-separated field names
>>> Point = namedtuple["Point", "x, y"]
>>> Point

>>> Point[4, 8]
Point[x=4, y=8]

>>> # A generator expression for the field names
>>> Point = namedtuple["Point", [field for field in "xy"]]
>>> Point

>>> Point[8, 16]
Point[x=8, y=16]
02. This is common to regular classes. Fortunately, there are ways to work around it. For example, you can add an special method to
>>> from collections import namedtuple

>>> # Create a namedtuple type, Point
>>> Point = namedtuple["Point", "x y"]
>>> issubclass[Point, tuple]
True

>>> # Instantiate the new type
>>> point = Point[2, 4]
>>> point
Point[x=2, y=4]

>>> # Dot notation to access coordinates
>>> point.x
2
>>> point.y
4

>>> # Indexing to access coordinates
>>> point[0]
2
>>> point[1]
4

>>> # Named tuples are immutable
>>> point.x = 100
Traceback [most recent call last]:
  File "", line 1, in 
AttributeError: can't set attribute
83 like this:

>>>

>>> from collections import namedtuple

>>> Point = namedtuple["Point", {"x", "y"}]
>>> Point[2, 4]
Point[y=2, x=4]
1

Here, you first import from

>>> from collections import namedtuple

>>> Person = namedtuple["Person", "name children"]
>>> john = Person["John Doe", ["Timmy", "Jimmy"]]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy']]
>>> id[john.children]
139695902374144

>>> john.children.append["Tina"]
>>> john
Person[name='John Doe', children=['Timmy', 'Jimmy', 'Tina']]
>>> id[john.children]
139695902374144

>>> hash[john]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unhashable type: 'list'
94. This function converts the data class into a tuple. Then you pass the resulting tuple to so you can build and return an from
>>> from collections import namedtuple

>>> # A list of strings for the field names
>>> Point = namedtuple["Point", ["x", "y"]]
>>> Point

>>> Point[2, 4]
Point[x=2, y=4]

>>> # A string with comma-separated field names
>>> Point = namedtuple["Point", "x, y"]
>>> Point

>>> Point[4, 8]
Point[x=4, y=8]

>>> # A generator expression for the field names
>>> Point = namedtuple["Point", [field for field in "xy"]]
>>> Point

>>> Point[8, 16]
Point[x=8, y=16]
03. With this addition, you can start iterating over Jane’s data.

Regarding memory consumption, named tuples are more lightweight than data classes. You can confirm this by creating and running a small script similar to the one you saw in the above section. To view the complete script, expand the box below.

Script to Compare Memory Usage:

>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
7 vs Data ClassShow/Hide

Here’s a script that compares memory usage between a

>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
7 and its equivalent data class:

>>> from collections import namedtuple

>>> Point = namedtuple["Point", {"x", "y"}]
>>> Point[2, 4]
Point[y=2, x=4]
2

In this script, you create a named tuple and a data class containing similar data. Then you compare their memory footprint.

Here are the results of running your script:

>>> from collections import namedtuple

>>> Point = namedtuple["Point", {"x", "y"}]
>>> Point[2, 4]
Point[y=2, x=4]
3

Unlike

>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
7 classes, data classes keep a per-instance to store . This contributes to a bigger memory footprint.

Next, you can expand the section below to see an example of code that compares

>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
7 classes and data classes in terms of their performance on attribute access.

Script to Compare Performance:

>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
7 vs Data ClassShow/Hide

The following script compares the performance of attribute access on a named tuple and its equivalent data class:

>>> from collections import namedtuple

>>> Point = namedtuple["Point", {"x", "y"}]
>>> Point[2, 4]
Point[y=2, x=4]
4

Here, you time the attribute access operation because that’s almost the only common operation between a named tuple and a data class. You can also time membership operations, but you would have to access the data class’

>>> from collections import namedtuple

>>> # A list of strings for the field names
>>> Point = namedtuple["Point", ["x", "y"]]
>>> Point

>>> Point[2, 4]
Point[x=2, y=4]

>>> # A string with comma-separated field names
>>> Point = namedtuple["Point", "x, y"]
>>> Point

>>> Point[4, 8]
Point[x=4, y=8]

>>> # A generator expression for the field names
>>> Point = namedtuple["Point", [field for field in "xy"]]
>>> Point

>>> Point[8, 16]
Point[x=8, y=16]
12 attribute to do it.

In terms of performance, here are the results:

>>> from collections import namedtuple

>>> Point = namedtuple["Point", {"x", "y"}]
>>> Point[2, 4]
Point[y=2, x=4]
5

The performance difference is minimal, so you can say that both data structures have equivalent performance when it comes to attribute access operations.

Remove ads

>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
7 vs
>>> from collections import namedtuple

>>> # A list of strings for the field names
>>> Point = namedtuple["Point", ["x", "y"]]
>>> Point

>>> Point[2, 4]
Point[x=2, y=4]

>>> # A string with comma-separated field names
>>> Point = namedtuple["Point", "x, y"]
>>> Point

>>> Point[4, 8]
Point[x=4, y=8]

>>> # A generator expression for the field names
>>> Point = namedtuple["Point", [field for field in "xy"]]
>>> Point

>>> Point[8, 16]
Point[x=8, y=16]
17

Python 3.5 introduced a module called to support function type annotations or . This module provides , which is a typed version of

>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
7. With
>>> from collections import namedtuple

>>> # A list of strings for the field names
>>> Point = namedtuple["Point", ["x", "y"]]
>>> Point

>>> Point[2, 4]
Point[x=2, y=4]

>>> # A string with comma-separated field names
>>> Point = namedtuple["Point", "x, y"]
>>> Point

>>> Point[4, 8]
Point[x=4, y=8]

>>> # A generator expression for the field names
>>> Point = namedtuple["Point", [field for field in "xy"]]
>>> Point

>>> Point[8, 16]
Point[x=8, y=16]
19, you can create
>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
7 classes with type hints. Following with the
>>> from collections import namedtuple

>>> # Create a namedtuple type, Point
>>> Point = namedtuple["Point", "x y"]
>>> issubclass[Point, tuple]
True

>>> # Instantiate the new type
>>> point = Point[2, 4]
>>> point
Point[x=2, y=4]

>>> # Dot notation to access coordinates
>>> point.x
2
>>> point.y
4

>>> # Indexing to access coordinates
>>> point[0]
2
>>> point[1]
4

>>> # Named tuples are immutable
>>> point.x = 100
Traceback [most recent call last]:
  File "", line 1, in 
AttributeError: can't set attribute
83 example, you can create an equivalent typed named tuple like this:

>>>

>>> from collections import namedtuple

>>> Point = namedtuple["Point", {"x", "y"}]
>>> Point[2, 4]
Point[y=2, x=4]
6

With

>>> from collections import namedtuple

>>> # A list of strings for the field names
>>> Point = namedtuple["Point", ["x", "y"]]
>>> Point

>>> Point[2, 4]
Point[x=2, y=4]

>>> # A string with comma-separated field names
>>> Point = namedtuple["Point", "x, y"]
>>> Point

>>> Point[4, 8]
Point[x=4, y=8]

>>> # A generator expression for the field names
>>> Point = namedtuple["Point", [field for field in "xy"]]
>>> Point

>>> Point[8, 16]
Point[x=8, y=16]
19, you can create tuple subclasses that support type hints and attribute access through the dot notation. Since the resulting class is a tuple subclass, it’s immutable as well.

A subtle detail to notice in the above example is that

>>> from collections import namedtuple

>>> # A list of strings for the field names
>>> Point = namedtuple["Point", ["x", "y"]]
>>> Point

>>> Point[2, 4]
Point[x=2, y=4]

>>> # A string with comma-separated field names
>>> Point = namedtuple["Point", "x, y"]
>>> Point

>>> Point[4, 8]
Point[x=4, y=8]

>>> # A generator expression for the field names
>>> Point = namedtuple["Point", [field for field in "xy"]]
>>> Point

>>> Point[8, 16]
Point[x=8, y=16]
19 subclasses look even more similar to data classes than named tuples.

When it comes to memory consumption, both

>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
7 and
>>> from collections import namedtuple

>>> # A list of strings for the field names
>>> Point = namedtuple["Point", ["x", "y"]]
>>> Point

>>> Point[2, 4]
Point[x=2, y=4]

>>> # A string with comma-separated field names
>>> Point = namedtuple["Point", "x, y"]
>>> Point

>>> Point[4, 8]
Point[x=4, y=8]

>>> # A generator expression for the field names
>>> Point = namedtuple["Point", [field for field in "xy"]]
>>> Point

>>> Point[8, 16]
Point[x=8, y=16]
19 instances use the same amount of memory. You can expand the box below to view a script that compares memory usage between the two.

Script to Compare Memory Usage:

>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
7 vs
>>> from collections import namedtuple

>>> # A list of strings for the field names
>>> Point = namedtuple["Point", ["x", "y"]]
>>> Point

>>> Point[2, 4]
Point[x=2, y=4]

>>> # A string with comma-separated field names
>>> Point = namedtuple["Point", "x, y"]
>>> Point

>>> Point[4, 8]
Point[x=4, y=8]

>>> # A generator expression for the field names
>>> Point = namedtuple["Point", [field for field in "xy"]]
>>> Point

>>> Point[8, 16]
Point[x=8, y=16]
17Show/Hide

Here’s a script that compares the memory usage of a

>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
7 and its equivalent
>>> from collections import namedtuple

>>> # A list of strings for the field names
>>> Point = namedtuple["Point", ["x", "y"]]
>>> Point

>>> Point[2, 4]
Point[x=2, y=4]

>>> # A string with comma-separated field names
>>> Point = namedtuple["Point", "x, y"]
>>> Point

>>> Point[4, 8]
Point[x=4, y=8]

>>> # A generator expression for the field names
>>> Point = namedtuple["Point", [field for field in "xy"]]
>>> Point

>>> Point[8, 16]
Point[x=8, y=16]
17:

>>> from collections import namedtuple

>>> Point = namedtuple["Point", {"x", "y"}]
>>> Point[2, 4]
Point[y=2, x=4]
7

In this script, you create a named tuple and an equivalent typed

>>> from collections import namedtuple

>>> # A list of strings for the field names
>>> Point = namedtuple["Point", ["x", "y"]]
>>> Point

>>> Point[2, 4]
Point[x=2, y=4]

>>> # A string with comma-separated field names
>>> Point = namedtuple["Point", "x, y"]
>>> Point

>>> Point[4, 8]
Point[x=4, y=8]

>>> # A generator expression for the field names
>>> Point = namedtuple["Point", [field for field in "xy"]]
>>> Point

>>> Point[8, 16]
Point[x=8, y=16]
19 instance. Then you compare the memory usage of both instances.

This time, the script that compares memory usage produces the following output:

>>> from collections import namedtuple

>>> Point = namedtuple["Point", {"x", "y"}]
>>> Point[2, 4]
Point[y=2, x=4]
8

In this case, both instances consume the same amount of memory, so there’s no winner this time.

Since

>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
7 classes and
>>> from collections import namedtuple

>>> # A list of strings for the field names
>>> Point = namedtuple["Point", ["x", "y"]]
>>> Point

>>> Point[2, 4]
Point[x=2, y=4]

>>> # A string with comma-separated field names
>>> Point = namedtuple["Point", "x, y"]
>>> Point

>>> Point[4, 8]
Point[x=4, y=8]

>>> # A generator expression for the field names
>>> Point = namedtuple["Point", [field for field in "xy"]]
>>> Point

>>> Point[8, 16]
Point[x=8, y=16]
19 subclasses are both subclasses of
>>> from collections import namedtuple

>>> Point1 = namedtuple["Point", "x y"]
>>> Point1


>>> class Point:
...     def __init__[self, x, y]:
...         self.x = x
...         self.y = y
...

>>> Point2 = Point
>>> Point2

7, they have a lot in common. In this case, you can time membership tests for fields and values. You can also time attribute access with the dot notation. Expand the box below to view a script that compares the performance of both
>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
7 and
>>> from collections import namedtuple

>>> # A list of strings for the field names
>>> Point = namedtuple["Point", ["x", "y"]]
>>> Point

>>> Point[2, 4]
Point[x=2, y=4]

>>> # A string with comma-separated field names
>>> Point = namedtuple["Point", "x, y"]
>>> Point

>>> Point[4, 8]
Point[x=4, y=8]

>>> # A generator expression for the field names
>>> Point = namedtuple["Point", [field for field in "xy"]]
>>> Point

>>> Point[8, 16]
Point[x=8, y=16]
19.

Script to Compare Performance:

>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
7 vs
>>> from collections import namedtuple

>>> # A list of strings for the field names
>>> Point = namedtuple["Point", ["x", "y"]]
>>> Point

>>> Point[2, 4]
Point[x=2, y=4]

>>> # A string with comma-separated field names
>>> Point = namedtuple["Point", "x, y"]
>>> Point

>>> Point[4, 8]
Point[x=4, y=8]

>>> # A generator expression for the field names
>>> Point = namedtuple["Point", [field for field in "xy"]]
>>> Point

>>> Point[8, 16]
Point[x=8, y=16]
17Show/Hide

The following script compares

>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
7 and
>>> from collections import namedtuple

>>> # A list of strings for the field names
>>> Point = namedtuple["Point", ["x", "y"]]
>>> Point

>>> Point[2, 4]
Point[x=2, y=4]

>>> # A string with comma-separated field names
>>> Point = namedtuple["Point", "x, y"]
>>> Point

>>> Point[4, 8]
Point[x=4, y=8]

>>> # A generator expression for the field names
>>> Point = namedtuple["Point", [field for field in "xy"]]
>>> Point

>>> Point[8, 16]
Point[x=8, y=16]
17 performance-wise:

>>> from collections import namedtuple

>>> Point = namedtuple["Point", {"x", "y"}]
>>> Point[2, 4]
Point[y=2, x=4]
9

In this script, you first create a named tuple and then a typed named tuple with similar content. Then you compare the performance of common operations over both data structures.

Here are the results:

>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
0

In this case, you can say that both data structures behave almost the same in terms of performance. Other than that, using

>>> from collections import namedtuple

>>> # A list of strings for the field names
>>> Point = namedtuple["Point", ["x", "y"]]
>>> Point

>>> Point[2, 4]
Point[x=2, y=4]

>>> # A string with comma-separated field names
>>> Point = namedtuple["Point", "x, y"]
>>> Point

>>> Point[4, 8]
Point[x=4, y=8]

>>> # A generator expression for the field names
>>> Point = namedtuple["Point", [field for field in "xy"]]
>>> Point

>>> Point[8, 16]
Point[x=8, y=16]
19 to create your named tuples can make your code even more explicit because you can add type information to the fields. You can also provide default values, add new functionality, and write for your typed named tuples.

In this section, you’ve learned a lot about

>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
7 and other similar data structures and classes. Here’s a table that summarizes how
>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
7 compares to the data structures covered in this section:

>>> from collections import namedtuple

>>> # Create a namedtuple type, Point
>>> Point = namedtuple["Point", "x y"]
>>> issubclass[Point, tuple]
True

>>> # Instantiate the new type
>>> point = Point[2, 4]
>>> point
Point[x=2, y=4]

>>> # Dot notation to access coordinates
>>> point.x
2
>>> point.y
4

>>> # Indexing to access coordinates
>>> point[0]
2
>>> point[1]
4

>>> # Named tuples are immutable
>>> point.x = 100
Traceback [most recent call last]:
  File "", line 1, in 
AttributeError: can't set attribute
95Data Class
>>> from collections import namedtuple

>>> # A list of strings for the field names
>>> Point = namedtuple["Point", ["x", "y"]]
>>> Point

>>> Point[2, 4]
Point[x=2, y=4]

>>> # A string with comma-separated field names
>>> Point = namedtuple["Point", "x, y"]
>>> Point

>>> Point[4, 8]
Point[x=4, y=8]

>>> # A generator expression for the field names
>>> Point = namedtuple["Point", [field for field in "xy"]]
>>> Point

>>> Point[8, 16]
Point[x=8, y=16]
19ReadabilitySimilarEqualEqualImmutabilityNoNo by default, yes if using
>>> from collections import namedtuple

>>> # A list of strings for the field names
>>> Point = namedtuple["Point", ["x", "y"]]
>>> Point

>>> Point[2, 4]
Point[x=2, y=4]

>>> # A string with comma-separated field names
>>> Point = namedtuple["Point", "x, y"]
>>> Point

>>> Point[4, 8]
Point[x=4, y=8]

>>> # A generator expression for the field names
>>> Point = namedtuple["Point", [field for field in "xy"]]
>>> Point

>>> Point[8, 16]
Point[x=8, y=16]
47YesMemory usageHigherHigherEqualPerformanceSlowerSimilarSimilarIterabilityYesNo by default, yes if providing
>>> from collections import namedtuple

>>> # A list of strings for the field names
>>> Point = namedtuple["Point", ["x", "y"]]
>>> Point

>>> Point[2, 4]
Point[x=2, y=4]

>>> # A string with comma-separated field names
>>> Point = namedtuple["Point", "x, y"]
>>> Point

>>> Point[4, 8]
Point[x=4, y=8]

>>> # A generator expression for the field names
>>> Point = namedtuple["Point", [field for field in "xy"]]
>>> Point

>>> Point[8, 16]
Point[x=8, y=16]
03Yes

With this summary, you’ll be able to choose the data structure that best fits your current needs. Additionally, you should consider that data classes and

>>> from collections import namedtuple

>>> # A list of strings for the field names
>>> Point = namedtuple["Point", ["x", "y"]]
>>> Point

>>> Point[2, 4]
Point[x=2, y=4]

>>> # A string with comma-separated field names
>>> Point = namedtuple["Point", "x, y"]
>>> Point

>>> Point[4, 8]
Point[x=4, y=8]

>>> # A generator expression for the field names
>>> Point = namedtuple["Point", [field for field in "xy"]]
>>> Point

>>> Point[8, 16]
Point[x=8, y=16]
19 allow you to add type hints, which is currently quite a desirable feature in Python code.

Subclassing
>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
7 Classes

Since

>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
7 classes are regular Python classes, you can subclass them if you need to provide additional functionalities, a docstring, a user-friendly string representation, and so on.

For example, storing the age of a person in an object isn’t considered a best practice. So you probably want to store the birth date and compute the age when needed:

>>>

>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
1

>>> from collections import namedtuple

>>> # Create a namedtuple type, Point
>>> Point = namedtuple["Point", "x y"]
>>> issubclass[Point, tuple]
True

>>> # Instantiate the new type
>>> point = Point[2, 4]
>>> point
Point[x=2, y=4]

>>> # Dot notation to access coordinates
>>> point.x
2
>>> point.y
4

>>> # Indexing to access coordinates
>>> point[0]
2
>>> point[1]
4

>>> # Named tuples are immutable
>>> point.x = 100
Traceback [most recent call last]:
  File "", line 1, in 
AttributeError: can't set attribute
83 inherits from
>>> from collections import namedtuple

>>> # A list of strings for the field names
>>> Point = namedtuple["Point", ["x", "y"]]
>>> Point

>>> Point[2, 4]
Point[x=2, y=4]

>>> # A string with comma-separated field names
>>> Point = namedtuple["Point", "x, y"]
>>> Point

>>> Point[4, 8]
Point[x=4, y=8]

>>> # A generator expression for the field names
>>> Point = namedtuple["Point", [field for field in "xy"]]
>>> Point

>>> Point[8, 16]
Point[x=8, y=16]
53, which is a
>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
7 class. In the subclass definition, you first add a docstring to describe what the class does. Then you set to an empty tuple, which prevents the automatic creation of a per-instance
>>> from collections import namedtuple

>>> # A list of strings for the field names
>>> Point = namedtuple["Point", ["x", "y"]]
>>> Point

>>> Point[2, 4]
Point[x=2, y=4]

>>> # A string with comma-separated field names
>>> Point = namedtuple["Point", "x, y"]
>>> Point

>>> Point[4, 8]
Point[x=4, y=8]

>>> # A generator expression for the field names
>>> Point = namedtuple["Point", [field for field in "xy"]]
>>> Point

>>> Point[8, 16]
Point[x=8, y=16]
12. This keeps your
>>> from collections import namedtuple

>>> # A list of strings for the field names
>>> Point = namedtuple["Point", ["x", "y"]]
>>> Point

>>> Point[2, 4]
Point[x=2, y=4]

>>> # A string with comma-separated field names
>>> Point = namedtuple["Point", "x, y"]
>>> Point

>>> Point[4, 8]
Point[x=4, y=8]

>>> # A generator expression for the field names
>>> Point = namedtuple["Point", [field for field in "xy"]]
>>> Point

>>> Point[8, 16]
Point[x=8, y=16]
53 subclass memory efficient.

You also add a custom to provide a nice string representation for the class. Finally, you add a to compute the person’s age using

>>> from collections import namedtuple

>>> # A list of strings for the field names
>>> Point = namedtuple["Point", ["x", "y"]]
>>> Point

>>> Point[2, 4]
Point[x=2, y=4]

>>> # A string with comma-separated field names
>>> Point = namedtuple["Point", "x, y"]
>>> Point

>>> Point[4, 8]
Point[x=4, y=8]

>>> # A generator expression for the field names
>>> Point = namedtuple["Point", [field for field in "xy"]]
>>> Point

>>> Point[8, 16]
Point[x=8, y=16]
59.

Remove ads

Measuring Creation Time:
>>> from collections import namedtuple

>>> Point1 = namedtuple["Point", "x y"]
>>> Point1


>>> class Point:
...     def __init__[self, x, y]:
...         self.x = x
...         self.y = y
...

>>> Point2 = Point
>>> Point2

7 vs
>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
7

So far, you’ve compared

>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
7 classes with other data structures according to several features. In this section, you’ll take a general look at how regular tuples and named tuples compare in terms of creation time.

Say you have an application that creates a ton of tuples dynamically. You decide to make your code more Pythonic and maintainable using named tuples. Once you’ve updated all your codebase to use named tuples, you run the application and notice some performance issues. After some tests, you conclude that the issues could be related to creating named tuples dynamically.

Here’s a script that measures the average time required to create several tuples and named tuples dynamically:

>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
2

In this script, you calculate the average time it takes to create several tuples and their equivalent named tuples. If you run the script from your command line, then you’ll get an output similar to the following:

>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
3

When you look at this output, you can see that creating

>>> from collections import namedtuple

>>> Point1 = namedtuple["Point", "x y"]
>>> Point1


>>> class Point:
...     def __init__[self, x, y]:
...         self.x = x
...         self.y = y
...

>>> Point2 = Point
>>> Point2

7 objects dynamically is a lot faster than creating similar named tuples. In some situations, such as working with large databases, the additional time required to create a named tuple can seriously affect your application’s performance, so keep an eye on this if your code creates a lot of tuples dynamically.

Conclusion

Writing Pythonic code is an in-demand skill in the Python development space. Pythonic code is readable, explicit, clean, maintainable, and takes advantage of Python idioms and best practices. In this tutorial, you learned about creating

>>> from collections import namedtuple

>>> Point = namedtuple["Point", ["x", "_y"]]
Traceback [most recent call last]:
  ...
ValueError: Field names cannot start with an underscore: '_y'
7 classes and instances and how they can help you improve the quality of your Python code.

In this tutorial, you learned:

  • How to create and use
    >>> from collections import namedtuple
    
    >>> Point = namedtuple["Point", ["x", "_y"]]
    Traceback [most recent call last]:
      ...
    ValueError: Field names cannot start with an underscore: '_y'
    
    7 classes and instances
  • How to take advantage of cool
    >>> from collections import namedtuple
    
    >>> Point = namedtuple["Point", ["x", "_y"]]
    Traceback [most recent call last]:
      ...
    ValueError: Field names cannot start with an underscore: '_y'
    
    7 features
  • When to use
    >>> from collections import namedtuple
    
    >>> Point = namedtuple["Point", ["x", "_y"]]
    Traceback [most recent call last]:
      ...
    ValueError: Field names cannot start with an underscore: '_y'
    
    7 instances to write Pythonic code
  • When to use a
    >>> from collections import namedtuple
    
    >>> Point = namedtuple["Point", ["x", "_y"]]
    Traceback [most recent call last]:
      ...
    ValueError: Field names cannot start with an underscore: '_y'
    
    7 instead of a similar data structure
  • How to subclass a
    >>> from collections import namedtuple
    
    >>> Point = namedtuple["Point", ["x", "_y"]]
    Traceback [most recent call last]:
      ...
    ValueError: Field names cannot start with an underscore: '_y'
    
    7 to add new features

With this knowledge, you can deeply improve the quality of your existing and future code. If you frequently use tuples, then consider turning them into named tuples whenever it makes sense. Doing so will make your code much more readable and Pythonic.

Mark as Completed

🐍 Python Tricks 💌

Get a short & sweet Python Trick delivered to your inbox every couple of days. No spam ever. Unsubscribe any time. Curated by the Real Python team.

Send Me Python Tricks »

About Leodanis Pozo Ramos

Leodanis is an industrial engineer who loves Python and software development. He's a self-taught Python developer with 6+ years of experience. He's an avid technical writer with a growing number of articles published on Real Python and other sites.

» More about Leodanis

Each tutorial at Real Python is created by a team of developers so that it meets our high quality standards. The team members who worked on this tutorial are:

Aldren

Bartosz

Joanna

Jacob

Master Real-World Python Skills With Unlimited Access to Real Python

Join us and get access to thousands of tutorials, hands-on video courses, and a community of expert Pythonistas:

Level Up Your Python Skills »

Master Real-World Python Skills
With Unlimited Access to Real Python

Join us and get access to thousands of tutorials, hands-on video courses, and a community of expert Pythonistas:

Level Up Your Python Skills »

What Do You Think?

Rate this article:

Tweet Share Share Email

What’s your #1 takeaway or favorite thing you learned? How are you going to put your newfound skills to use? Leave a comment below and let us know.

Commenting Tips: The most useful comments are those written with the goal of learning from or helping out other students. and get answers to common questions in our support portal.

Bài mới nhất

Chủ Đề