pythoncollectionsnamedtuple

How can Python by used to support a record type? (i.e. mutable namedtuple)


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.

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

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.

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


Solution

  • Python ≥3.3

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

    Python <3.3

    You could use 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.