部分应用列表理解

2024-05-19 00:20:43 发布

您现在位置:Python中文网/ 问答频道 /正文

我开始学习Haskell,结果发现,在那里,你可以将列表理解变成一个部分应用的函数。换句话说,它返回一个接受列表的函数,然后对列表运行列表理解。在

示例:

boomBangs xs = [ if x < 10 then "BOOM!" else "BANG!" | x <- xs, odd x]

boomBangs can then be called with the actual "xs" argument.

我的问题:在Python中有什么方法可以做到这一点吗?我到处找了找,找不到一条路,但我可能遗漏了一些东西。在

这样做是非常有价值的。在

编辑:

我的意思似乎有些混乱。在

我希望能够定义列表理解,而不必在以后将列表交给它。在

我们的想法是,列表理解实际上变成了一个接受一个参数的函数,即要处理的列表。在

例如,我可以:

^{pr2}$

然后在代码后面的某个地方:

my_new_func(range(10)) # Returns the answer

这是一种非常好的函数式编程方法。在

第二次编辑:

这里有一个我想做的方法,但是我想知道有没有更好的方法:

boomBangs = lambda lst: [actual list comprehension]

boomBangs(range(10))

Tags: the方法函数编辑示例列表ifhaskell
3条回答

您可以使用内置函数mapfilterfunctools.partial来实现这一点,但与其他海报所做的一样,与制作Python函数相比,结果可能不太清楚或不方便。然而,部分应用程序和currying确实是可以在Python中使用的强大技术。在

在en.wikipedia.org/wiki/Partial_应用程序在

在en.wikipedia.org/wiki/Currying在

使用toolzPython包可以很容易地演示这一点,该包包含许多在其他函数式编程语言中常见的函数实用程序。toolz还有一个方便的curried名称空间,我将使用它来重现您的示例:

>>> # define our primitive functions for clarity
>>> boombang = lambda x: "BOOM!" if x < 10 else "BANG!"
>>> is_odd = lambda x: x % 2 == 1

>>> # given a list, using built-in functions we can do
>>> map(boombang, filter(is_odd, range(20)))
['BOOM!', 'BOOM!', 'BOOM!', 'BOOM!', 'BOOM!', 'BANG!', 'BANG!', 'BANG!', 'BANG!', 'BANG!']

>>> # if we want to provide the list later, we can do
>>> from toolz.curried import map, filter, compose
>>> boomBangs = compose(map(boombang), filter(is_odd))

>>> # ... Now we have our input list, so let's use it!
>>> list(boomBangs(range(20))
['BOOM!', 'BOOM!', 'BOOM!', 'BOOM!', 'BOOM!', 'BANG!', 'BANG!', 'BANG!', 'BANG!', 'BANG!']

注意在最后一个例子中,我们如何只向mapfilter传递一个参数。这是咖喱!函数在提供最后一个参数时被调用,我们确实得到了相同的结果。在

让我们分别使用mapfilter来澄清到底发生了什么:

^{pr2}$

您可以使用python的列表理解:

xs = ["BOOM!" if x < 10 else "BANG!" for x in range(20) if x % 2 == 1]

要将其合并到函数中:

^{pr2}$

您还可以使用lambda

>>> boombang = lambda xs: ["BOOM!" if x < 10 else "BANG!" for x in xs if x % 2 == 1]
>>> boombang(range(-10, 20))
['BOOM!', 'BOOM!', 'BOOM!', 'BOOM!', 'BOOM!', 'BOOM!', 'BOOM!', 'BOOM!', 'BOOM!', 'BOOM!', 'BANG!', 'BANG!', 'BANG!', 'BANG!', 'BANG!']
>>> 

列表理解是逆向的,定义在结尾处,语句在开头。在这个列表理解的开头,我们说"BOOM!" if x < 10 else "BANG!",它翻译成:

if x < 10:
    xs.append("BOOM!")
else:
    xs.append("BANG!")

在第二部分中,我们将x定义为数字0到20(包括0到20)中的每一项。之后,我们使用python的模,确保只有当x是奇数时,这个循环才会完成。在


>>> xs = ["BOOM!" if x < 10 else "BANG!" for x in range(20) if x % 2 == 1]
>>> xs
['BOOM!', 'BOOM!', 'BOOM!', 'BOOM!', 'BOOM!', 'BANG!', 'BANG!', 'BANG!', 'BANG!', 'BANG!']
>>> 

特别之处不是列表理解,而是函数定义。恰好函数返回了一个列表。因此,只需在Python中将其定义为普通函数即可。在

boomBangs = lambda xs: ["BOOM!" if x < 10 else "BANG!" for x in xs if odd(x)]

def boomBang(xs):
  return ["BOOM!" if x < 10 else "BANG!" for x in xs if odd(x)]

如果你想让它变懒,就用genex代替。在

^{pr2}$

相关问题 更多 >

    热门问题