【问题标题】:Applying function to iterable?将函数应用于可迭代?
【发布时间】:2014-03-13 15:32:32
【问题描述】:

我刚刚写了这个函数:

def _apply(mols, fn, *args, **kwargs):
    return [fn(m, *args, **kwargs) for m in mols if m ]

我开始思考:

  1. 可以使用map 重写吗?
  2. 这是否已经在 python 的某个地方实现了?

据我所知,map 不能将参数传递给函数,另一方面,它可能会以某种方式进行优化,并使用一些部分绑定或 lambda,我可以使用 map 重新实现它。会有好处吗?

【问题讨论】:

  • 你能以某种方式尝试描述代码的用途吗?
  • @PauloBu - 首先,我更改了示例代码,之前的代码很糟糕。它做了什么(或者我的意图是什么),它将带有 args 和 kwargs 的函数应用于 itarable 的每个项目。
  • 请注意,map 仅在与内置函数一起使用时速度很快,因此最好使用 LC。
  • @AshwiniChaudhary 即使def 函数会更快,对吧?
  • @thefourtheye 我不这么认为,唯一的区别是带有lambda 的表达式必须先执行额外的步骤,将lambda 编译为代码对象。

标签: python algorithm function functional-programming list-comprehension


【解决方案1】:

虽然我认为你目前拥有的东西很漂亮,但这样的东西可能会起作用:

map(lambda m: fn(m, *args, **kwargs), filter(None, mols))

mols 中过滤出所有计算结果为False 的元素,然后将函数fn 应用于这些元素。

算法的时间复杂度为O(n)

如果您的mols 真的很大,您可能需要使用itertools

from itertools import imap, ifilter

list(imap(lambda m: fn(m, *args, **kwargs), ifilter(None, mols)))

【讨论】:

  • 这里有同样的评论 - 使用你的解决方案与我的相比有什么好处吗?
  • @mnowotka 我对此表示怀疑。如果您有大量要处理的事情,使用 itertools 可能有助于提高速度。你的版本很好。
【解决方案2】:

是的,你可以

from functools import partial

clean = partial(filter, None)

def _apply(mols, fn, *args, **kwargs):
    f = partial(fn, *args, **kwargs)
    return map(f, clean(mols))

def foo(m, a, b, c=123):
    return [m, a, b, c]

print _apply([11,22,'',33], foo, 'aa', 'bb', c=475)

(在python2中,考虑itertools.imap/ifilter而不是map/filter以避免临时列表)。

上面说明了“部分应用”,更优雅的是柯里化,即当使用比预期更少的参数调用时返回自身的部分应用版本的函数。 Python 没有内置 currying,但作为装饰器很容易实现(参见 https://stackoverflow.com/a/9458386/989121):

@curry
def join_three(a,b,c):
    return '%s-%s-%s' % (a,b,c)

mols = [11,22,33]
print map(join_three('aa', 'bb'), mols)
# prints ['aa-bb-11', 'aa-bb-22', 'aa-bb-33']

也就是说,函数式风格在 python 中是不受欢迎的,在大多数情况下,推导式和生成器更“pythonic”。

【讨论】:

  • 是的,但它比我的解决方案更好吗?
  • 或者干脆return map(partial(fn, *args, **kwargs), mols)?
  • 这种技术有一个名字,叫做函数柯里化 :)
  • @thefourtheye:这是“部分应用”,而不是“currying”。相似但不同的东西。
  • @thefourtheye:我在帖子中添加了一个示例。
猜你喜欢
  • 2021-02-25
  • 1970-01-01
  • 2012-04-27
  • 2017-12-11
  • 2021-04-16
  • 2013-01-16
  • 2019-12-21
  • 1970-01-01
  • 2013-06-03
相关资源
最近更新 更多