大多数pythonic形式用于映射一系列语句?

时间:2008-12-09 08:06:41

标签: python coding-style idioms

这一直困扰着我一段时间。在学习Python之前我学习了Haskell,所以我一直喜欢将许多计算作为映射到列表中。这是由列表理解(我在这里给出pythonic版本)精美表达的:

result = [ f(x) for x in list ]

但在很多情况下,我们希望在x上执行多个语句,比如说:

result = [ f(g(h(x))) for x in list ]

这很快变得笨重,难以阅读。

我对此的正常解决方案是将其扩展回for循环:

result = []
for x in list:
  x0 = h(x)
  x1 = g(x0)
  x2 = f(x1)
  result.append(x2)

关于这一点困扰我的一件事就是必须初始化空列表'结果'。这是一个微不足道的事情,但它让我感到不快。我想知道是否有任何替代等效形式。一种方法可能是使用本地函数(这是他们在Python中调用的吗?)

def operation(x):
  x0 = h(x)
  x1 = g(x0)
  x2 = f(x1)
  return x2
result = [ operation(x) for x in list ]

上述两种形式中的任何一种都有什么特别的优点/缺点吗?或者是否有更优雅的方式?

7 个答案:

答案 0 :(得分:5)

您可以轻松地在Python中执行函数组合。

这是一个创建新函数的方法的演示,该函数是现有函数的组合。

>>> def comp( a, b ):
    def compose( args ):
        return a( b( args ) )
    return compose

>>> def times2(x): return x*2

>>> def plus1(x): return x+1

>>> comp( times2, plus1 )(32)
66

这是function composition更完整的食谱。这应该让它看起来不那么笨重。

答案 1 :(得分:3)

遵循最符合您口味的风格 我不担心表现;只有在你真正看到某些问题的情况下,你才能尝试转向不同的风格。

除了您的建议之外,还有其他一些可能的建议:

result = [f(
              g(
                h(x)
                )
              )
            for x in list]

使用渐进式列表推导:

result = [h(x) for x in list]
result = [g(x) for x in result]
result = [f(x) for x in result]

同样,这只是风格和品味的问题。选择你最喜欢的那个,坚持下去: - )

答案 2 :(得分:2)

如果这是你经常做的事情,并且有几个不同的陈述,你可以写一些像

def seriesoffncs(fncs,x):
    for f in fncs[::-1]:
        x=f(x)
    return x

其中fncs是一个函数列表。所以seriesoffncs((f,g,h),x)会返回 F(克(H(X)))。 这样,如果你以后在你的代码中需要锻炼h(q(g(f(x)))),你只需要执行seriesoffncs((h,q,g,f),x)而不是为一个新的操作函数每个功能组合。

答案 3 :(得分:1)

如果您只关注最后的结果,那么您的最后答案是最好的。对于任何看着它的人​​来说,这是很明显的。

我经常使用任何开始变得复杂的代码并将其移动到函数中。这基本上用作该代码块的注释。 (无论如何,任何复杂的代码都可能需要重写,并将它放在一个函数中,我可以返回并稍后处理它)

def operation(x):
  x0 = h(x)
  x1 = g(x0)
  x2 = f(x1)
  return x2
result = [ operation(x) for x in list]

答案 4 :(得分:1)

dagw.myopenid.com函数的变体:

def chained_apply(*args):
    val = args[-1]
    for f in fncs[:-1:-1]:
        val=f(val)
    return val

现在你可以调用:

而不是seriesoffncs((h,q,g,f),x)
result = chained_apply(foo, bar, baz, x)

答案 5 :(得分:1)

据我所知,Python中的组合没有内置/本机语法,但你可以编写自己的函数来编写东西而不会有太多麻烦。

def compose(*f):
    return f[0] if len(f) == 1 else lambda *args: f[0](compose(*f[1:])(*args))

def f(x): 
    return 'o ' + str(x)

def g(x): 
    return 'hai ' + str(x)

def h(x, y): 
    return 'there ' + str(x) + str(y) + '\n'

action = compose(f, g, h)
print [action("Test ", item) for item in [1, 2, 3]]

当然,不需要在理解之外进行组合。

print [compose(f, g, h)("Test ", item) for item in [1, 2, 3]]

这种编写方式适用于任何数量的函数(以及递归限制),内部函数有任意数量的参数。

答案 6 :(得分:0)

有些情况下最好回到for-loop,是的,但更多时候我更喜欢这些方法之一:

使用适当的换行符和缩进来保持可读性:

result = [blah(blah(blah(x)))
          for x in list]

或者提取(足够)逻辑到另一个函数中,正如您所提到的那样。但不一定是本地的;如果你能看到一种合理的方法来分解功能,那么Python程序员更喜欢从平面到嵌套结构。

我也从功能编程世界来到Python,并分享你的偏见。