[Tutor] appending/updating values dict key value pairs

Steven D'Aprano steve at pearwood.info
Sun Jun 23 12:33:20 CEST 2013


On 23/06/13 19:42, Sivaram Neelakantan wrote:
> On Sun, Jun 23 2013,Alan Gauld wrote:
>
>
> [snipped 21 lines]
>
>> But we normally call methods via the object instance rather than the
>> class so simplifying this further we get:
>>
>> b['a'].append('c')
>>
>
> Thanks for the detailed explanation.
>
> I've sort of used a dict of this sort {'a': [1,2,'fff'] } in my
> programs and I've noticed that I've got to unpack the list with
> hardcoded list positions when I retrieve the value of a key.
>
> I think I'd be better off, if I did something of
>
> {'a' : ['foo': 1, 'bar':2, 'offset': 'fff'] }


That won't work; you need to make the inner value a dict using {}, not a list using [].

> wouldn't that be better from a maintainability POV?  Are there any
> examples of such?  Or is there a 'struct' option for python?  I don't
> want to use OO methods for now.

Python doesn't have structs in the sense you mean. (But see below for alternatives.) There is a struct module for working with low-level C-style bytes, ints, doubles etc. but that's not what you want.

In this case, you can stick with nested dicts:

{'a' : {'foo': 1, 'bar':2, 'offset': 'fff'}}


It may be less typing if you use this format:

{'a': dict(foo=1, bar=2, offset='fff'),
  'b': dict(foo=2, bar=6, offset='fe0'),
  'c': dict(foo=4, bar=9, offset='d02'),
  }


Instead of working with dicts, it isn't very hard to create your own struct-like class:


class MyStruct(object):
     def __init__(self, foo, bar, offset):
         self.foo = foo
         self.bar = bar
         self.offset = offset


A little tedious, but it only needs to be done once, then:

{'a': MyStruct(1, 2, 'fff'),
  'b': MyStruct(2, 6, 'fe0'),
  'c': MyStruct(4, 9, 'd02'),
  }

The advantage is that you can both read and write the attributes:

s = MyStruct(4, 9, 'd02')
s.foo = 42
print(s.bar)


A third alternative is namedtuple, from the collections module.


from collections import namedtuple

MyStruct = namedtuple('MyStruct', 'foo bar offset')
s = MyStruct(4, 9, 'd02')
print(s.bar)


The advantage here is that namedtuple automatically includes extra "polish", such as printing nicely. The only negative is that namedtuples are immutable: once created, you cannot modify them, you have to create a new one:

# this doesn't work
s.foo = 42
# instead do this:
s = MyStruct(42, s.bar, s.offset)


This is deliberate, not a bug. But if you can live with that limitation of namedtuples, then they are the recommended way to get the equivalent of a Pascal record or C struct. Otherwise just create a quick little class as needed.


-- 
Steven


More information about the Tutor mailing list