简体   繁体   English

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

[英]Is it possible to call a function (not a built in function) inside a list comprehension in python?

Say we have a list: 说我们有一个清单:

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

and we have created a function called add(): 我们创建了一个名为add()的函数:

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

which runs through a list of numbers X, adding the next element in the list to the previous sum. 它运行一个数字列表X,将列表中的下一个元素添加到前一个总和。 So for each element X[i], we have: 因此对于每个元素X [i],我们有:

1
3
6
10
15
21
28
36
45

Now, what if I want to put these results in a list again, by making use of a list comprehension. 现在,如果我想通过使用列表理解将这些结果再次放入列表中,该怎么办呢? Is it possible to call a function such as add() within a list comprehension, given that it is possible to apply built in functions inside list comprehensions? 是否可以在列表推导中调用add()等函数,因为可以在列表推导中应用内置函数?

I have tried the following: 我尝试过以下方法:

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

which gives 这使

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

instead of 代替

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

Why am I getting NoneType values in this list? 为什么我在此列表中获得NoneType值?

You could do this with yield to keep with your original format: 您可以使用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

Yes, it is possible to call functions inside list comprehensions. 是的,可以在列表推导中调用函数。 Your example is fine - it's the add() function that is to be blamed. 你的例子很好 - 这是要被责备的add()函数。 What you need is make the add() function receive an argument - the list to sum. 你需要的是使add()函数接收一个参数 - 要求汇总的列表。

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

This way, the list comprehension would look like this: 这样,列表理解将如下所示:

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

This is equivalent to: 这相当于:

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

Which turns out to be a list of prefix sums - the thing you want. 结果是前缀总和列表 - 你想要的东西。

Your approach won't work, because your add() is stateless. 你的方法不起作用,因为你的add()是无状态的。 You need something that maintains state between different invocations of add() , otherwise add() will always produce the same output. 您需要在add()不同调用之间维护状态的东西,否则add()将始终生成相同的输出。

One solution to accomplish what you want is itertools.accumulate() . 完成所需的一个解决方案是itertools.accumulate() See Equivalent of Haskell scanl in python for a discussion. 有关讨论,请参阅python中的等效Haskell scanl

Other answers here have suggested using a list comprehension that involves a range() . 这里的其他答案建议使用涉及range()的列表理解。 While that would work, it would also be inefficient, as an O(n^2) algorithm that recomputes the cumulative sums from scratch for each entry. 虽然这可行,但它也是低效的,因为O(n ^ 2)算法从头开始重新计算每个条目的累积和。

#!/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

produces this: 产生这个:

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

Yes, it is possible to call any function in list comprehension. 是的,可以在列表理解中调用任何函数。

Also note that in Python 2.x you cannot have print in list comprehension because print is not a function (in Python 2). 另请注意,在Python 2.x中,您无法在列表中理解print ,因为print不是函数 (在Python 2中)。

To your example - it could look like this, using an add() function that works with shared state (the s variable): 对于您的示例 - 它可能看起来像这样,使用与共享状态( s变量)一起使用的add()函数:

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]

See other answers how to do it without that shared state so you don't get different results when you forget to set s = 0 . 请参阅其他答案如何在没有共享状态的情况下执行此操作,以便在忘记设置s = 0时不会得到不同的结果。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM