是否可以在python中的列表解析中调用函数(不是内置函数)?

时间:2014-08-23 18:46:18

标签: python function list-comprehension nested

说我们有一个清单:

X = [1,2,3,4,5,6,7,8]

我们创建了一个名为add()的函数:

def add():
  sum = 0
  result = 0
  for e in X:
    sum = sum + e
    return sum
add()

通过数字列表X运行,将列表中的下一个元素添加到前一个总和。因此对于每个元素X [i],我们有:

1
3
6
10
15
21
28
36
45

现在,如果我想通过使用列表理解将这些结果再次放入列表中,该怎么办?是否可以在列表推导中调用add()等函数, 鉴于可以在列表推导中应用内置函数吗?

我尝试了以下内容:

L = [add() for e in X]
print L

给出了

[None, None, None, None, None, None, None, None, None]

而不是

[1,3,6,10,15,21,28,36,45]

为什么我在此列表中获得NoneType值?

5 个答案:

答案 0 :(得分:4)

您可以使用yield执行此操作以保持原始格式:

    X = [1,2,3,4,5,6,7,8]

    def add():
      sum = 0
      for e in X:
        sum = sum + e
        yield sum

    L = [value for value in add()]
    print L

答案 1 :(得分:2)

是的,可以在列表推导中调用函数。你的例子很好 - 这是add()函数被指责。 你需要的是让add()函数接收一个参数 - 要求的列表。

def add(elements):
    sum = 0
    for el in elements:
        sum += el
    return sum

这样,列表理解将如下所示:

L = [add(X[:i+1]) for i in xrange(len(X))]
[1, 3, 6, 10, 15, 21, 28, 36]

这相当于:

L = [add(X[:1]), add(X[:2]), ..., add(X[:8])]

结果是前缀总和列表 - 你想要的东西。

答案 2 :(得分:2)

你的方法不起作用,因为你的add()是无国籍的。您需要在add()的不同调用之间维护状态的内容,否则add()将始终生成相同的输出。

实现目标的一个解决方案是itertools.accumulate()。有关讨论,请参阅Equivalent of Haskell scanl in python

此处的其他答案建议使用涉及range()的列表理解。虽然这可行,但它也是低效的,因为O(n ^ 2)算法从头开始重新计算每个条目的累积和。

答案 3 :(得分:0)

#!/usr/bin/env python
"""
produce a list that adds each item to the previous item
this list [1,2,3,4] will produce this list [1,3,6,10]
"""

def accumulate(my_list, previous = 0):
    for i in my_list:
        previous += i
        yield previous

x = [1,2,3,4,5,6,7,8,9]
new_list = []
new_list = [i for i in accumulate(x)]
print x   
print new_list

产生这个:

[1, 2, 3, 4, 5, 6, 7, 8, 9]
[1, 3, 6, 10, 15, 21, 28, 36, 45]

答案 4 :(得分:0)

是的,可以在列表理解中调用任何函数。

另请注意,在Python 2.x中,由于print is not a function(在Python 2中),因此无法在列表推导中使用print

对于您的示例 - 它可能看起来像这样,使用add()函数使用共享状态(s变量):

s = 0   # better not use name 'sum' as it is already a builtin function
def add(i):
    global s
    s += i
    return s
X = [1, 2, 3, 4, 5, 6, 7, 8]
print [add(i) for i in X]
# prints [1, 3, 6, 10, 15, 21, 28, 36]
# but beware the global shared state! for example when called again:
print [add(i) for i in X]
# prints [37, 39, 42, 46, 51, 57, 64, 72]

如果没有该共享状态,请参阅其他答案,以便在忘记设置s = 0时不会得到不同的结果。