2016-01-22 81 views
0

David Beazley's talk on generators,他演示瞭如何從任何一個參數的功能從而創建一個發生器功能:將任何單參數函數轉換爲生成器函數?

def generate(func): 
    def gen_func(s): 
     for item in s: 
      yield func(item) 
    return gen_func 

,並說明其與math.sqrt

gen_sqrt = generate(math.sqrt) 
for x in gen_sqrt(xrange(100)): 
    print x 

那麼,爲什麼:

gen_sum = generate(sum) 
for x in gen_sum([1,2,3,4,5]): 
    print x 

產生於:


TypeError         Traceback (most recent call last) 
<ipython-input-73-ef521f2bbfc8> in <module>() 
     1 gen_sum = generate(sum) 
----> 2 for x in gen_sum(1): 
     3  print x 

<ipython-input-50-3c0ba12c2429> in gen_func(s) 
     1 def generate(func): 
     2  def gen_func(s): # closure 
----> 3   for item in s: 
     4    yield func(item) 
     5  return gen_func 

TypeError: 'int' object is not iterable 

更準確地說,函數是一個單參數函數是這種方法工作的一個必要但不足的條件?而另一個必要條件是單個參數必須是單個項目(而不是序列)?

+1

一個總和需要兩個參數......該函數必須是隻需要一個參數的函數......您希望上面實際執行的操作是什麼? 'math.sqrt(25)'vs'sum(25)'我認爲問題變得清晰了。 –

+0

你顯示回溯的異常似乎來自對'gen_sum'的不同調用,而不是你如上所示(這也會引發一個'TypeError',它帶有相同的消息,但在代碼的不同部分以及其他原因)。 – Blckknght

+2

它必須是一個單參數函數**,它接受所傳遞的值* *** gen_sum([(1,2),(3,4,5)])'很好,例如。 – jonrsharpe

回答

2

你是正確的,都是必要條件:

def generate(func): 
    def gen_func(s): 
     for item in s:   # <--- requires s to be interable 
      yield func(item) # <--- requires func to accept a single argument 
    return gen_func 

所以在

gen_sum = generate(func) 
for x in gen_sum(s): 
    print x 

func必須接受一個參數和s必須是迭代。

3

您正在傳遞其元素類型錯誤的列表。當然,這不會起作用,因爲gen_sqrt(['a', 's', 'd', 'f'])不會起作用。

你需要傳遞gen_sum的事情列出來是有意義的呼籲,sum如其他列表:

for x in gen_sum([[1, 2], [3, 4]]): 
    print x 

輸出:

3 
7 
1

generatemap發電機版本。

map(lambda x: x*2, range(5)) [0, 2, 4, 6, 8] 

它將輸入範圍和應用函數應用到範圍中的每個元素。

generate也是這樣,但它不返回一個列表。它會產生每次轉換的結果。

現在看看你的例子。第一個結果是什麼? sum(1)

sum期望一個列表,而不是一個整數,因此錯誤消息。

相關問題