在python中将函数应用于iterable?

时间:2014-02-14 10:16:47

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

我刚写了这个函数:

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

我开始思考:

  1. 可以使用map重写吗?
  2. 这是否已经在python的某个地方实现了?
  3. 据我所知,map无法将参数传递给函数,另一方面,它可能以某种方式进行优化并使用一些部分绑定或lambdas我可以使用map重新实现它。这会有益吗?

2 个答案:

答案 0 :(得分:4)

是的,你可以

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以避免临时列表。

上面说明了“部分应用程序”,更优雅的是currying,即一个函数在使用少于预期的参数调用时返回自身的部分应用版本。 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”。

答案 1 :(得分:2)

虽然我认为你现在拥有的东西非常漂亮,但这样的东西可能有用:

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

过滤掉评估为mols的{​​{1}}中的所有元素,然后将函数False应用于这些元素。

算法的时间复杂度为fn

如果您的O(n)非常大,则可能需要使用mols

itertools