Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python: overloading tuple multi-assignment capabilities?

Tags:

python

tuples

So i have made my own dict-based named-tuple class:

class t(dict):
   def __getattr__(self, v):
      try:
         return self[v]
      except KeyError:
         raise AttributeError("Key " + str(v) + " does not exist.")
   def __init__(self, *args, **kwargs):
      for source in args:
         for i, j in source.items():
            self[i] = j
      for i, j in kwargs.items():
         self[i] = j

>>> thing = t(cow=10, moo='moooooooo')
>>> thing.cow
10
>>> thing.moo
'moooooooo'

The point of using a dict is so i can use the **splat operator, as well as so the whole thing can be json'd as a dict. The double for loop in init is so I can immediately re-construct it from the dict after deserialization.

The only thing I'm missing is the multi-assignment thing you can do with tuples, like

>>> thing = (1, 3, ('blargh', 'mooo'))
>>> a, b, (c, d) = thing
>>> a
1
>>> b
3
>>> c
'blargh'
>>> d
'mooo'

Is there any way I can get this sort of behavior with my own custom datatype? Is there any function that I can override or some class I can inherit from to get this behaviour?

like image 275
Li Haoyi Avatar asked Aug 19 '11 05:08

Li Haoyi


1 Answers

Yes. Implement __iter__().

class unpackable_dict(dict):
    def __iter__(self):
        return (self[key] for key in sorted(self.keys()))

d = unpackable_dict(a=1, b=2)
a, b = d

The reason you normally can't unpack values from a dict like you can a tuple is that dicts don't have a defined order. I've used a generator expression to get the items out in the sorted order of their keys. You might consider using an OrderedDict instead, though.

like image 152
kindall Avatar answered Oct 28 '22 20:10

kindall