2012-12-18 49 views
1

我有一個消費者生成器管道。從這些消費者的最後,我想在某個時間點返回結果。此作品:從消費者生成器返回單個值

class StopIterationWithResult(StopIteration): 
    def __init__(self, result): 
     super(StopIterationWithResult, self).__init__() 
     self.result = result 

# for definition fo consumer decorator see http://www.python.org/dev/peps/pep-0342/ 
@consumer 
def waitfor3(): 
    while True: 
     value = (yield) 
     if value == 3: 
      raise StopIterationWithResult('Hello') 

c = waitfor3() 
for i in range(10): 
    try: 
     print 'calling', i 
     c.send(i) 
    except StopIterationWithResult as r: 
     print 'stopped', r.result 
     break 

有沒有更好的方法?例如,如果由於return陳述引發StopIteration,您能否訪問生成器的返回值?

按照要求通過@alexis,這裏是一個管道的例子:

class StopIterationWithResult(StopIteration): 
    def __init__(self, result): 
     super(StopIterationWithResult, self).__init__() 
     self.result = result 

@consumer 
def add1_filter(consumer): 
    while True: 
     value = (yield) 
     consumer.send(value+1) 

@consumer 
def waitfor3(): 
    while True: 
     value = (yield) 
     print 'got', value 
     if value == 3: 
      raise StopIterationWithResult('Hello') 

c = waitfor3() 
f = add1_filter(c) 
for i in range(10): 
    try: 
     print 'calling', i 
     f.send(i) 
    except StopIterationWithResult as r: 
     print 'stopped', r.result 
     break 

這裏還有與@Martijn Pieters的答案是相同的 - 使得過濾器有點更難看,但:

@consumer 
def add1_filter(consumer): 
    result = None 
    while True: 
     value = (yield result) 
     result = consumer.send(value+1) 

@consumer 
def waitfor3(): 
    while True: 
     value = (yield) 
     print 'got', value 
     if value == 3: 
      yield 'Hello' 
      break 

c = waitfor3() 
f = add1_filter(c) 
r = None 
for i in range(10): 
    try: 
     print 'calling', i 
     r = f.send(i) 
    except StopIteration: 
     print 'stopped', r 
     break 
+3

我不明白爲什麼你不只是值後'產生的最後一個對象= 3'再提升一個普通'StopIteration'。 – kreativitea

+0

你能舉一個例子_with_管道嗎?沒有改進的東西很難提出改進。 – alexis

回答

2

收益率是雙向的。在右邊的表達式中使用,它將接收並用作語句,它將生成表達式的結果。

只是產生這一結果的值:

def waitfor3(): 
    while True: 
     value = (yield) 
     if value == 3: 
      yield 'Hello' 
      break 

c = waitfor3() 
for i in range(10): 
    try: 
     print 'calling', i 
     result = c.send(i) 
    except StopIteration: 
     print 'stopped', result 
     break 
+0

在意識到需要修改過濾器後未接受答案。希望有更好的答案。 – Sebastian

+0

它不工作,除非你提供比實際需要的更多的值。 (使用範圍(4)而不是範圍(10))或者只是注意它打印「調用4」。 – Sebastian

0

你並不需要繼承StopIteration,您可以訪問args你傳遞給它的構造函數。見http://docs.python.org/2/library/exceptions.html#exceptions.BaseException

@consumer 
def add1_filter(consumer): 
    while True: 
     value = (yield) 
     consumer.send(value+1) 

@consumer 
def waitfor3(): 
    while True: 
     value = (yield) 
     print 'got', value 
     if value == 3: 
      # This doesn't work: 
      # return 456 # SyntaxError: 'return' with argument inside generator 
      # But this does: 
      raise StopIteration(123) 

c = waitfor3() 
f = add1_filter(c) 
for i in range(10): 
    try: 
     print 'calling', i 
     f.send(i) 
    except StopIteration as r: 
     print 'stopped (StopIteration)', r, type(r.args[0]) 
     break 
相關問題