Why does Python not support record type? (i.e. mutable namedtuple)

Salil picture Salil · Mar 8, 2011 · Viewed 39.1k times · Source

Why does Python not support a record type natively? It's a matter of having a mutable version of namedtuple.

I could use namedtuple._replace. But I need to have these records in a collection and since namedtuple._replace creates another instance, I also need to modify the collection which becomes messy quickly.

Background: I have a device whose attributes I need to get by polling it over TCP/IP. i.e. its representation is a mutable object.

Edit: I have a set of devices for whom I need to poll.

Edit: I need to iterate through the object displaying its attributes using PyQt. I know I can add special methods like __getitem__ and __iter__, but I want to know if there is an easier way.

Edit: I would prefer a type whose attribute are fixed (just like they are in my device), but are mutable.

Answer

tzot picture tzot · Mar 30, 2011

Python <3.3

You mean something like this?

class Record(object):
    __slots__= "attribute1", "attribute2", "attribute3",

    def items(self):
        "dict style items"
        return [
            (field_name, getattr(self, field_name))
            for field_name in self.__slots__]

    def __iter__(self):
        "iterate over fields tuple/list style"
        for field_name in self.__slots__:
            yield getattr(self, field_name)

    def __getitem__(self, index):
        "tuple/list style getitem"
        return getattr(self, self.__slots__[index])

>>> r= Record()
>>> r.attribute1= "hello"
>>> r.attribute2= "there"
>>> r.attribute3= 3.14

>>> print r.items()
[('attribute1', 'hello'), ('attribute2', 'there'), ('attribute3', 3.1400000000000001)]
>>> print tuple(r)
('hello', 'there', 3.1400000000000001)

Note that the methods provided are just a sample of possible methods.

Python ≥3.3 update

You can use types.SimpleNamespace:

>>> import types
>>> r= types.SimpleNamespace()
>>> r.attribute1= "hello"
>>> r.attribute2= "there"
>>> r.attribute3= 3.14

dir(r) would provide you with the attribute names (filtering out all .startswith("__"), of course).