So far we have seen many of the built-in Python data structures. We’ll now discuss the object-oriented features of them. We start with the object class.

1. Empty objects

The most basic Python built-in is the object class, that actually we already used implicitly. Theoretically, we can instantiate an object without writing a sublcass:

>>> o = object()
>>> o.x = 5
AttributeError: 'object' object has no attribute 'x'

We cannot set any attributes on an object that was instantiated directly. Python developers did that to save a lot of memory. When Python allows an object to have arbitrary attributes, it takes a certain amount of system memory to keep track of what attributes each object has, for storing both the attribute name and its value. Even if no attributes are stored, memory is allocated to make it possible to add attributes. Since in Python every class extends the object class, this small amount of memory would quickly become a large amount of memory. However, it’s easy to create an empty object class and set an attribute:

>>> class MyObject:
...     pass
 
>>> m = MyObject()
>>> m.x = "hello"
>>> m.x
'hello'

2. Tuples and named tuples

Tuples are objects that can store a specific number of other objects in sequence. They’re immutable, so we cannot add, remove, or replace objects. The primary benefit of tuples’ immutability is that a tuple of immutable objects has a hash value, allowing us to use them as keys in dictionaries, and members of set.

The primary purpose of a tuple is to aggregate different pieces of data together into one container. Often, tuples are associated with physical dimensions: (x, y) pair as coordinates or (r, g, b) as an rgb colour.

Tuples are usually wrapped into parentheses (but it’s not mandatory; it’s just to make them more readable) and values are separated by a comma. Commas are required when we’re putting a tuple inside other objects, like a function call, or a list comprehension. Indeed the following two declarations are exactly the same:

stock = "AAPL", 133.52, 53.15, 137.98
stock2 = ("AAPL", 133.52, 53.15, 137.98)

The extreme case is a tuple with one element, when the comma is requires:

a = (42,)
b = 42,

It’s possible to unpack a tuple into different variables:

a, b, c, d = ("AAPL", 133.52, 53.15, 137.98)

We can access to one of the variables in a tuple or extract a piece of a tuple by using the same syntax we use for a list:

>>> tuple1 = ("AAPL", 133.52, 53.15, 137.98)
>>> tuple1[2]
53.15
 
>>>> tuple1[1:3]
(133.52, 53.15)

Accessing tuple members directly is not always recommended. The index values are indeed called magic numbers because they seem to come out in the code with no meaning. A suggestion is to use tuples only when you know that all the values are going to be useful at once.

An alternative for clarifying the contents of tuples is the typing.NamedTuple class.

2.1 Named tuples via typing.NamedTuple

3. Dataclasses