【问题标题】:Turning any single-argument function into a generator function?将任何单参数函数转换为生成器函数?
【发布时间】:2016-01-22 21:38:29
【问题描述】:

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

是否更准确地说,作为单参数函数的函数是这种方法工作的必要但不充分条件?另一个必要条件是单个参数必须是单个项目(而不是序列)?

【问题讨论】:

  • a sum 需要两个参数......该函数必须是一个只需要一个参数的函数......您期望上面的实际作用是什么? math.sqrt(25) vs sum(25) 我认为问题是什么已经很清楚了..
  • 您显示回溯的异常似乎来自对 gen_sum 的调用,而不是您在上面显示的调用(这也会引发带有相同消息的 TypeError,但在代码的不同部分和不同的原因)。
  • 它必须是一个单参数函数接受你传递的值的种类! gen_sum([(1, 2), (3, 4, 5)]) 可以,例如.
  • @Blckknght 很好看。但最终还是同样的错误。
  • @JoranBeasley sum 接受一个参数。在我上面的例子中,那个单一的参数是一个列表。

标签: python function generator yield


【解决方案1】:

您传递的列表中的元素类型错误。当然它不会起作用,原因与gen_sqrt(['a', 's', 'd', 'f']) 不起作用的原因相同。

您需要向gen_sum 传递一个可以调用sum 的列表,例如其他列表:

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

输出:

3
7

【讨论】:

    【解决方案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】:

      generatemap 的生成器版本。

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

      它接受输入范围并对范围内的每个元素应用函数。

      generate 做同样的事情,但它不返回列表。它产生每个转换的结果。

      现在看看你的例子。第一个结果会是什么? sum(1).

      sum 需要一个列表,而不是整数,因此会出现错误消息。

      【讨论】:

        猜你喜欢
        • 2023-03-24
        • 2021-01-03
        • 2019-11-29
        • 1970-01-01
        • 2019-11-13
        • 2015-12-07
        • 2020-02-10
        • 2011-11-08
        • 2017-04-15
        相关资源
        最近更新 更多