While perusing some of the unanswered posts on Stack Overflow, I came across an interesting question which was asking how to mimic the behavior of CPython's small ints and some other built-ins like True and False. That is, there is enforced only one instance with each value. For example

x = 12
y = 12
x == y # True
x is y # Also True

You can contrast this with, for example, (sufficiently long) strings which don't have this property.

x = "Hello World"
y = "Hello World"
x == y # True
x is y # This is False

So how can we craft a way to get this property for custom classes? Let's go straight to the code.

from collections import namedtuple

def singleton_namedtuple(class_name, fields):
    nt = namedtuple(class_name, fields)

    class NT(nt):
        _dict = {}

        def __new__(cls, *args):
            if args not in cls._dict:
                print("making new {} w/ {}", class_name, args)
                cls._dict[args] = super().__new__(cls, *args)
            return cls._dict[args]

    return NT

Use the function like this:

Variable = singleton_namedtuple('Variable', ['letter', 'index'])

a = Variable('one', 1)
b = Variable('two', 2)
c = Variable('two', 2)

print(a == b) # False
print(a is b) # False
print(b == c) # True
print(b is c) # True

The factory method singleton_namedtuple creates a class based on a namedtuple. Because the class is inheriting from tuple, it is immutable which is a required property since immutability prevents distinct objects which are not equal from becoming equal and breaking the property of equality implying identity.

Overriding the __new__ method allows us to prevent the creation of a new object when an equivalent object already exists.

The biggest caveat here is that the objects in the namedtuple must be hashable and immutable. Hashability is required for the code to run, and immutability is required to maintain equality implying identity.