如何在功能上写这个表达式?

时间:2018-03-20 22:19:37

标签: python lambda functional-programming

我想在功能上重写以下python代码:

lst = [0.0] * 10
for pos in [2,5]:
    lst[pos] = 1.0

这是我的尝试,但不正确:

lst = (lambda zeros:
          map(
              lambda pos: zeros[pos] = 1.0, [2,5])
      )([0.0] * 10)

我得到的错误是lambda cannot contain assignment

使用列表理解,解决方案是:

lst = [ 1.0 if x in [2,5] else 0.0 for x in range(10) ]

3 个答案:

答案 0 :(得分:2)

我更喜欢你自己的答案中的列表理解,但是如果我更多地使用功能性触摸,我想我会使用lambda函数和map

lazy = map(lambda element: 1 if element in [2,5] else 0, range(10))

请注意,map是Python 3中的一个惰性迭代器。如果您想要一个已评估的list,则必须将该行括在显式list(...)构造函数中:

lst = list(map(lambda element: 1 if element in [2,5] else 0, range(10)))

答案 1 :(得分:1)

列表理解方法可能更好,但如果您正在寻找功能如何:

lst = [0.0] * 10
lst = map(lambda (i, x): 1.0 if i in {2,5} else x, enumerate(lst))
#[0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0]

通过使用enumerate(lst)作为map()的可迭代,我们得到索引和值。在这种情况下,如果i位于{2, 5},我们就会得0。否则,我们保留值x

如果您正在使用python3,则必须使用map()将呼叫包裹到list()。但是,这种方法是not recommended,因为它浪费地创建了一个列表。

答案 2 :(得分:1)

另一种方法是使用泛型函数unfold

def unfold (f, acc):
  return f ( lambda x, next: [x] + unfold (f, next)
           , lambda x: [x] 
           , acc                          
           )

def main (ones):
  def value (i):
    return 1 if i in ones else 0   
  return unfold ( lambda next, done, i:
                    done (value (i)) if i >= 10 else next (value (i), i + 1)
                , 0
                )

print (main ( { 2, 5 }))
# [0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0]

unfold可以用有趣的方式使用

def alphabet ():
  return unfold ( lambda next, done, c:
                    done (c)            
                      if c == 'z' else
                        next (c, chr (ord (c) + 1))
                , 'a'
                )

print (alphabet ())
# ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']

Python的lambda语法非常严格,其笨拙的三元语法使得函数表达式难以编写。在下面的示例中,我们使用一些命令式语法预定义函数gen以帮助提高可读性,然后我们将其传递给unfold - 此程序还显示state可以是复杂值

def fib (n):
  def gen (next, done, state):
    (n, a, b) = state
    if n == 0:
      return done (a)
    else:
      return next (a, (n - 1, b, a + b))
  return unfold (gen, (n, 0, 1))

print (fib (20))
# [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765]

当然所有这些痛苦都存在 - 这是一个表明我们做错事的信号。经验丰富的python程序员永远不会像上面那样写mainalphabetfib。所以它不是 pythonic (正如他们所说),但它是功能,希望能回答你的问题。

下面,我们大大简化了unfold - 我们要求用户返回一个编码其选择的元组,而不是将nextdone助手传递给用户lambda:{{1 } {} (value, None)是序列中的最后一个值,value将生成下一个值并继续下一个状态。

这里的权衡是(value, nextState)稍微复杂一点,但它需要用户知道编写程序的特殊元组信令。之前,unfoldnext让用户不再担心这种担忧。无论哪种方式都很好,我分享这只是为了给另一种选择

done