Python函数可以使用生成器并将生成器返回到其生成的输出的子集吗?

2024-05-17 16:16:58 发布

您现在位置:Python中文网/ 问答频道 /正文

假设我有这样一个生成器函数:

import random
def big_gen():
  i = 0
  group = 'a'
  while group != 'd':
    i += 1
    yield (group, i)
    if random.random() < 0.20:
      group = chr(ord(group) + 1)

示例输出可能是: (“a”,1),(“a”,2),(“a”,3),(“a”,4),(“a”,5),(“a”,6),(“a”,7),(“a”,8),(“b”,9),(“c”,10),(“c”,11),(“c”,12),(“c”,13)

我想把这个分成三组:A组,B组,C组。我想为每一组配备一个发电机。然后我把生成器和群字母传递给一个子函数。子功能示例:

^{pr2}$

预期输出为:

These numbers are in group a:
1
2
3
4
5
6
7
8
These numbers are in group b:
9
These numbers are in group c:
10
11
12
13

如何在不更改big_gen()或printer()的情况下完成此操作,并避免同时将整个组存储在内存中?(在现实生活中,群体是巨大的


Tags: 函数inimport示例ifdefgrouprandom
2条回答

你这里有点小问题。您希望函数to printer()为每个组获取一个生成器,但实际上您有一个生成所有组的生成器。在我看来,你有两个选择:

1)改变big_gen()以产生发电机:

import random
def big_gen():
  i = 0
  group = 'a'
  while group != 'd':
    def gen():
        i += 1
        yield i
        if random.random() < 0.20:
            group = chr(ord(group) + 1)
    yield group, gen

 from itertools import imap
 imap(lambda a: printer(*a), big_gen())

2)更改printer()以保持状态并在组更改时通知(保留原来的big_gen()函数):

^{pr2}$

当然,这是你想要的:

import itertools
import operator

def main():
  for let, gen in itertools.groupby(big_gen(), key=operator.itemgetter(0)):
    secgen = itertools.imap(operator.itemgetter(1), gen)
    printer(let, secgen)

groupby负责这里的大部分工作,key=只告诉它分组依据哪个字段。在

生成的生成器需要包装在imap中,这是因为您指定了printer签名对数字进行迭代器,而实际上,groupby返回迭代器,覆盖它在此处输入的相同项,2项元组加上一个字母后接一个数字,但这与你的问题标题并不完全相关。在

这个标题的答案是,是的,Python函数可以很好地完成您想要的工作itertools.groupby事实上就是这样。我建议您仔细研究itertools模块,它是一个非常有用的工具(而且还提供了出色的性能)。在

相关问题 更多 >