Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to expand a tuple in a yield?

I am trying to expand a tuple in a yield statement but I'm getting a SyntaxError. Is this even possible, or is the * operator only for function calls?

Here is an example below:

class Inner(object):
    def __init__(self):
        self._vals = {'a': 1,
                      'b': 2,
                      'c': 3,
                      'd': 4}

    def __iter__(self):
        for key, val in self._vals.items():
            yield key, val

class Outer(object):
    def __init__(self):
        self._morevals = {"foo": Inner(),
                          "bar": Inner()}

    def __iter__(self):
        for key, moreval in self._morevals.items():
            for val in moreval:
                yield key, *val    # !!! <--- This is where the error is

object_under_test = Outer()

for outer_key, inner_key, inner_value in object_under_test:
    print("{} {} {}".format(outer_key, inner_key, inner_value))

    # Want:
    # foo a 1
    # foo b 2
    # foo c 3
    # foo d 4
    # bar a 1
    # bar b 2
    # bar c 3
    # bar d 4

Instead, I'm getting this error:

    yield key, *val
               ^
SyntaxError: invalid syntax
like image 822
TinyTheBrontosaurus Avatar asked Dec 11 '22 10:12

TinyTheBrontosaurus


2 Answers

Add parentheses, either around the tuple:

yield (key, *val)

yield is special here in that the form only accepts an expression list, not a starred_list form.

like image 133
Martijn Pieters Avatar answered Dec 13 '22 00:12

Martijn Pieters


You'll need to parenthesize it. In short, use:

yield (key, *val)

Alternatively, you could shorten it by using yield from with a comprehension. All in all, your __iter__ looking like:

 def __iter__(self):
    items = self._morevals.items()
    yield from ((k, *v) for k, vals in items for v in vals)

Similarly, using yield from in ClassOne.__iter__:

def __iter__(self):
    yield from self._vals.items()
like image 26
Dimitris Fasarakis Hilliard Avatar answered Dec 13 '22 00:12

Dimitris Fasarakis Hilliard