> From: oscar.j.benja...@gmail.com > Date: Thu, 14 Apr 2016 21:34:39 +0100 > Subject: Re: [Tutor] question about __copy__ and __deepcopy__ > To: sjeik_ap...@hotmail.com > CC: tutor@python.org > > On 14 April 2016 at 20:38, Albert-Jan Roskam <sjeik_ap...@hotmail.com> wrote: > > Hi, > > > > Lately I have been using the "mutable namedtuple" shown below a lot. I > > found it somewhere on StackOverflow or ActiveState or something. > > In its original form, it only had an __init__ method. > > I don't know about your copy/deepcopy stuff. It looked fine to me but > I'm not very experienced in that area. I wonder what this mutable > namedtuple is for though. > > Looking at it: > > > class Record(dict): > > > > def __init__(self, *args, **kwargs): > > super(Record, self).__init__(*args, **kwargs) > > self.__dict__ = self > > It's not so much a mutable namedtuple as an "attribute dict". It's a > dict whose keys can be accessed as attributes - because it is its own > instance dict. Of course it also has dict attributes like pop, items > etc. (see dir(dict) for a list). The reason that dicts use d[k] rather > than d.k for accessing keys is to be able to store arbitrary keys > without conflicting with the dict's methods which are attributes. > > A namedtuple is something very different. It subclasses tuple and the > whole idea is that an instance is lightweight (not having an attribute > dict) and hashable and imutable etc. A mutable version of that might > just look like: > > class Point(object): > # No instance dict: > __slots__ = ['x', 'y'] > > def __init__(self, x, y): > self.x = x > self.y = y > > It depends what you really want it for though.
HI Oscar, Ok, I agree that "mutable namedtuple" is a misnomer. I started using a regular namedtuple, and then I wanted something with similar functionality, but with the possibility to update/mutate the fields. The AttrDict was the option I liked. The order of the fields is rarely important in my case. I can easily use the AttrDict with SqlAlchemy, too. What I like about both namedtuple and AttrDict is attribute lookup: that makes code so, so, soooo much easier to read. This seems to be a nice generalization of your code: class Point(object): def __init__(self, **kwargs): Point.__slots__ = kwargs.keys() for k, v in kwargs.items(): setattr(self, k, v) point = Point(x=1, y=2, z=3) print point.x point.x = 42 print point.x I have no experience with __slots__ (but I think I roughly know what it's for). I expected this to fail: point.remark = "booh" point Out[36]: <__main__.Point at 0x7f282de9ccd0> point.remark Out[37]: 'booh' How can it be that __slots__ may be extended once the Point class has been instantiated? (sorry if this post is a bit long --this is just so much fun!) If I add a convenience getter/setter, the setter does indeed only seem to work for attributes that were in __slots__ already (here "z") class Point(object): def __init__(self, **kwargs): Point.__slots__ = kwargs.keys() for k, v in kwargs.items(): setattr(self, k, v) @property def values(self): return {attr: getattr(self, attr) for attr in Point.__slots__} @values.setter def values(self, d): for attr, value in d.items(): print "setting", attr, value setattr(self, attr, value) point = Point(x=1, y=2, z=3) print point.x point.x = 42 print point.x print point.values point.values = dict(a=1, b=2, c=3) print point.values ## no a, b, c here! point.values = dict(a=1, b=2, z=444) print point.values # z is updated, though! Thank you! Albert-Jan _______________________________________________ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor