[英]Generator comprehension using another generator
I am trying to write a method that returns a Generator
.我正在尝试编写一个返回
Generator
的方法。 The end result of these two methods is to get a combination of two lists in the form: 'A #1', 'B #1', ..., 'F #9'
这两种方法的最终结果是得到以下形式的两个列表的组合:
'A #1', 'B #1', ..., 'F #9'
FLATS = ['A', 'B', 'C', 'D', 'E', 'F']
def generate_nums() -> Generator[str, None, None]:
prefix = '#'
for num in range(10):
code = ''.join([prefix, str(num)])
yield code
def generate_room_numbers() -> Generator[str, None, None]:
room_nums = generate_nums()
yield (' '.join([flat_name, room_num]) for room_num in room_nums for flat_name in FLATS)
if __name__ == "__main__":
result = generate_room_numbers()
result = next(result) # I hate this. How do I get rid of this?
for room in result:
print(room)
This gives me the correct outcome.这给了我正确的结果。 Although, my annoyance is the line
result = next(result)
.虽然,我的烦恼是行
result = next(result)
。 Is there a better way to do this?有一个更好的方法吗? I looked at this answer as well as the
yield from
syntax but I can barely understand generators enough as it is.我查看了这个答案以及
yield from
syntax 但我几乎不能完全理解生成器。
You could use a generator expression and a f-string:您可以使用生成器表达式和 f 字符串:
FLATS = ['A', 'B', 'C', 'D', 'E', 'F']
room_numbers = (f'{letter} #{i}' for i in range(1, 10) for letter in FLATS)
for room in room_numbers:
print(room)
Output: Output:
A #1
B #1
C #1
.
.
.
D #9
E #9
F #9
It will be best if the yield
statement is put inside an explicit loop rather than trying to yield a generator.最好将
yield
语句放在显式循环中,而不是尝试生成生成器。
Your generate_room_numbers
should look like this:你的
generate_room_numbers
应该是这样的:
def generate_room_numbers():
for flat_name in FLATS:
room_nums = generate_nums()
for room_num in room_nums:
yield (' '.join([flat_name, room_num]))
Note that the generate_nums()
is called inside the flat_name
loop, because you cannot repeatedly iterate over the same iterator that it returns;请注意,
generate_nums()
是在flat_name
循环内调用的,因为您不能重复迭代它返回的同一个迭代器; after iterating through it, it is exhausted and generate_nums
will raise StopIteration
every time (so that iterating produces an empty sequence).在遍历它之后,它被耗尽并且
generate_nums
每次都会引发StopIteration
(以便迭代产生一个空序列)。
(If generate_nums
is expensive, then you could of course do nums = list(generate_nums())
outside the flat_name
loop and then iterate over that inside the loop, but if this requires potentially a lot of memory, then it could defeat much of the point in using a generator in the first place.) (如果
generate_nums
很昂贵,那么你当然可以在flat_name
循环之外执行nums = list(generate_nums())
然后在循环内迭代它,但是如果这可能需要很多 memory,那么它可能会击败大部分点首先使用生成器。)
The rest of your code is unchanged except that the result = next(result)
in the main code is removed, but for convenience, here is the whole thing:您的代码的 rest 除了主代码中的
result = next(result)
被删除之外没有变化,但是为了方便起见,这里是整个事情:
FLATS = ['A', 'B', 'C', 'D', 'E', 'F']
def generate_nums():
prefix = '#'
for num in range(10):
code = ''.join([prefix, str(num)])
yield code
def generate_room_numbers():
for flat_name in FLATS:
room_nums = generate_nums()
for room_num in room_nums:
yield (' '.join([flat_name, room_num]))
if __name__ == "__main__":
result = generate_room_numbers()
# result = next(result) <<==== NOT NEEDED ANY MORE
for room in result:
print(room)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.