2009-08-01 60 views
5

比方說,我有發電機功能是這樣的: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) 

實施例輸出可能是: ( '一個',1),( '一個',2),( 'A',3),( (a',5),('a',6),('a',7),('a',8),('b',9),('c ',10),('c',11),('c',12),('c',13)

我想把它分成三組:A組,B組和組C.我想爲每個組都配一臺發電機。然後,我會將生成器和組信轉換爲子功能。子功能的一個示例:

def printer(group_letter, generator): 
    print "These numbers are in group %s:" % group_letter 
    for num in generator: 
    print "\t%s" % num 

所需的輸出將是:

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()或打印機(),並避免在存儲器中存儲整個組在一旦? (在現實生活中,這些羣體是巨大的

+1

在現實生活中,可以多次行走大型發電機嗎?或者數據是否以某種不可挽回的方式消耗?如果我正確理解你的例子,那麼調用random()的狀態不會被存儲在任何有用的地方,所以你不能再次使用該生成器。 – Nelson 2009-08-01 00:43:55

回答

8

當然,這你想要做什麼:

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模塊,這是一個非常有用的工具(並且可以提供出色的性能)。

0

這裏有一個小問題。你需要使用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)更改打印機(),以保持狀態,並通知當組變化(保持原來的big_gen()函數):

def printer(generator): 
    group = None 
    for grp, num in generator: 
    if grp != group: 
     print "These numbers are in group %s:" % grp 
     group = grp 
    print "\t%s" % num