简体   繁体   中英

Python: Yield Dict Elements in generators?

Before I say a word, let me thank the community for being the authoritative location for my programming queries as of recent. And pretend those compliments weren't expressed using words. Anyway, the law of probability dictated that I stumble across something I couldn't find using the versatile search bar, so I've decided to explicitly ask for the first time. Maybe I just wasn't searching using Pythonic-enough lingo. Or perhaps I suck at Googling/Stackoverflowing. Regardless...

I'm toying with Python coroutines and generators. From what I can gather, you can do anything a generator-comprehension can with producer coroutines, albeit more verbosely. I'm currently using Python 3, although any answers regarding Python 2 as well wouldn't go a miss.

So I'm assuming the following code fragments are equivalent:

one_to_three = (num for num in range(1, 4))

...

def one_to_three():
    for num in range(1, 4):
        yield num

one_to_three_gen = one_to_three()

It works on my Python installation. If I ignore the redundancy-so-common-in-examples featured in that code, I see that the generator comprehension maps easily to the generator made by the producer coroutine. Being Dr. Pragmatic, I tried mapping the same concept to dicts, given that dict comprehensions already exist, with me thinking these two would be equivalent:

one_to_three_doubles = {num : num * 2 for num in range(1, 4)}

...

def one_to_three_doubles():
    for num in range(1, 4):
        yield num : num * 2

one_to_three_doubles_gen = one_to_three_doubles()

The first one works, but the second does not. It flags a syntax error on the colon on the 3rd line.

Now, either I'm slipping up very slightly on the syntax, or I have a massive misunderstanding of how producer coroutines work. I suspect it's failing for the same reason you can't make a coroutine return a list as opposed to a generator, but I don't really know.

So yeah, a fix to that error is basically what I'm asking for; thanks in advance. I'd prefer a answer that tells me the answer as opposed to giving me a whole new way of achieving the result, but obviously if it's the only way...

Dict comprehensions do work like list/set comprehensions and generator expressions - an X comprehension with a "body" of expr for vars in iterable is pretty much equivalent to X(expr for vars in iterable) - and you already know how to turn a generator expression into a generator. But note the "pretty much" bit, as a literal translation doesn't work (as you noticed) and isn't necessary at all (doesn't make the implementation much easier and would actually be quite hacky).

Dict comprehension just have a tiny bit of syntactic sugar to look more like dict literals (the colon). Semantically, it's not necessary - there is nothing special about it. Stop and think about it for a second: The dict comprehension must produce two values on each iteration, a key and a value. That's exactly what the colon stands for - (key, value) pairs (remember that dict accepts an iterable of (key, value) pairs). You can't use that syntactic sugar outside of dict comprehensions, but you can just use tuples for the pairs. Therefore, the equivalent generator would be:

def one_to_three_doubles():
    for num in range(1, 4):
        yield num, num * 2

I wanted to generate a dict from yield in a python function and found this question. Below is code for returning a dict.

def _f():
    yield 'key1', 10
    yield 'key2', 20

def f(): return dict(_f())

print(f())
# Output:
{'key1': 10, 'key2': 20}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM