[英]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.