1

Why isn't this unpacking work for my dictionary?

The dictionary is build as follows:

cutDict = {'scene1': [('scene3', 1001, 1125)]} 

I'm trying to unpack this like:

for key, (cut, fIn, fOut) in cutDict.iteritems():   
    print key 
    print cut
    print fIn
    print fOut

but this results in:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: need more than 1 value to unpack

Right now I'm building the dictionary via:

cutDict.setdefault(itm, [])
for cutItm in itm.cut_items_ordered:
    cutInOut = (mostcutItm, recentcutItm.cut_item_in, callcutItm.cut_item_out)
    cutDict[itm].append(cutInOut): 
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
Petter Östergren
  • 973
  • 4
  • 14
  • 27
  • @MartijnPieters I did just copy the directory out of my terminal. this is how it comes out : [(, 1001, 1125)] – Petter Östergren Apr 26 '17 at 13:18
  • @MartijnPieters Unfortunetly im not sure why it adds both [] and () im just built a var that is being populated by other vars 3 in total and the appended to the dict. – Petter Östergren Apr 26 '17 at 13:20
  • Then you have a list still, containing 1 element, a tuple. Please do put that into your question, and add the full traceback of the exception you get. You don't need the `self.` reference here, it'll make for an easier to reproduce [mcve] if you dropped that. The `` objects are also a bit of a distraction. – Martijn Pieters Apr 26 '17 at 13:20
  • 1
    We can't tell you how to fix the nesting issue because you don't share how you build the dictionary. That'd be a separate question too. – Martijn Pieters Apr 26 '17 at 13:21
  • Thank you for the editing @MartijnPieters. – Petter Östergren Apr 26 '17 at 13:29
  • 1
    From your edit it is clear you can potentially have 0 or more than 1 `cutInOut` structure in your list, at which point your unpacking operation is not feasible anymore. See my updated answer. – Martijn Pieters Apr 26 '17 at 13:30

1 Answers1

8

Your value is not a tuple, it is a list with one element, which is a tuple; the nested tuple has 3 elements. Because the outer container has only one element, your unpacking assignment fails.

The following does work, by adding another layer, provided there is always exactly one element:

for key, ((cut, fIn, fOUT),) in cutDict.iteritems():

or you can use list syntax:

for key, [(cut, fIn, fOUT)] in cutDict.iteritems():

Demo:

>>> cutDict = {'scene1': [('scene3', 1001, 1125)]}
>>> for key, ((cut, fIn, fOUT),) in cutDict.iteritems():
...     print key, cut, fIn, fOut
...
scene1 scene3 1001 1125
>>> for key, [(cut, fIn, fOUT)] in cutDict.iteritems():
...     print key, cut, fIn, fOut
...
scene1 scene3 1001 1125

Alternatively, remove the nesting, the outer list is redundant.

If your dictionary really can have more than one item in it, then the outer list is of course not redundant, but then you can't use iterable unpacking either. You'd have to add another loop instead:

for key, cuts in cutDict.iteritems():
    for cut, fIn, fOUT in cuts:
        # ...
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • @PetterÖstergren: yes, thereby removing the problem altogether. – Martijn Pieters Apr 26 '17 at 13:11
  • 2
    Martijn, can you say a word on why you would be using `iteritems()` here, rather than just `for key in cutDict`? I guess the whole _for X, Y_ loop would not be as concise when doing `for key in cutDict`, as I would have to pull in `cutDict[key]` as well? Is that it? Thanks! – patrick Apr 26 '17 at 13:15
  • 2
    @patrick: that's exactly it. Why only loop over the keys when you are also always going to use the values? – Martijn Pieters Apr 26 '17 at 13:18
  • For what it's worth, I didn't realize Python unpacking was smart enough to nest unpacks in this way. I never fail to learn something from Martijn's answers, no matter how long I work in the language. – Adam Smith Apr 26 '17 at 13:22