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 nee
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.
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).
In the closely related Existence of mutable named tuple in Python? question 13 tests are used for comparing 6 mutable alternatives to namedtuple
.
The latest namedlist 1.7 passes all of these tests with both Python 2.7 and Python 3.5 as of Jan 11, 2016. It is a pure python implementation.
The second best candidate according to these tests is the recordclass which is a C extension. Of course, it depends on your requirements whether a C extension is preferred or not.
For further details, especially for the tests, see Existence of mutable named tuple in Python?
You could do something like thisdict
subclass which is its own __dict__
. The basic concept is the same as that of the ActiveState AttrDict recipe, but the implementation is simpler. The result is something more mutable than you need since both an instance's attributes and their values are changeable. Although the attributes aren't ordered, you can iterate through the current ones and/or their values.
class Record(dict):
def __init__(self, *args, **kwargs):
super(Record, self).__init__(*args, **kwargs)
self.__dict__ = self
Is there any reason you can't use a regular dictionary? It seems like the attributes don't have a specific ordering in your particular situation.
Alternatively, you could also use a class instance (which has nice attribute access syntax). You could use __slots__
if you wish to avoid having a __dict__
created for each instance.
I've also just found a recipe for "records", which are described as mutable named-tuples. They are implemented using classes.
Update:
Since you say order is important for your scenario (and you want to iterate through all the attributes) an OrderedDict
seems to be the way to go. This is part of the standard collections
module as of Python 2.7; there are other implementations floating around the internet for Python < 2.7.
To add attribute-style access, you can subclass it like so:
from collections import OrderedDict
class MutableNamedTuple(OrderedDict):
def __init__(self, *args, **kwargs):
super(MutableNamedTuple, self).__init__(*args, **kwargs)
self._initialized = True
def __getattr__(self, name):
try:
return self[name]
except KeyError:
raise AttributeError(name)
def __setattr__(self, name, value):
if hasattr(self, '_initialized'):
super(MutableNamedTuple, self).__setitem__(name, value)
else:
super(MutableNamedTuple, self).__setattr__(name, value)
Then you can do:
>>> t = MutableNamedTuple()
>>> t.foo = u'Crazy camels!'
>>> t.bar = u'Yay, attribute access'
>>> t.foo
u'Crazy camels!'
>>> t.values()
[u'Crazy camels!', u'Yay, attribute access']
Based on several useful tricks gathered over time, this "frozenclass" decorator does pretty much everything needed: http://pastebin.com/fsuVyM45
Since that code is over 70% documentation and tests, I won't say more here.