16

是否有可能有类似的东西:

list1 = ...

currentValue = 0
list2 = [currentValue += i, i for i in list1]

我试过了,但没有用?写这些的正确语法是什么?

编辑:打印语句就是一个例子。实际上我是在循环外增加一个值。

4

9 回答 9

32

语句不能进入 Python 中的表达式;这是一种故意用语言设计的复杂功能。对于这个问题,请尝试使用确实使其成为语言的复杂性:生成器。手表:

def total_and_item(sequence):
    total = 0
    for i in sequence:
        total += i
        yield (total, i)

list2 = list(total_and_item(list1))

生成器保留到目前为止看到的项目的运行记录,并将其添加到每个项目的前缀,就像您的示例尝试做的那样。当然,一个简单的循环可能更简单,它在顶部创建一个空列表,并且只调用 append() 很多!:-)

于 2009-04-21T22:45:01.677 回答
4

我不太确定您要做什么,但可能类似于

list2 = [(i, i*2, i) for i in list1]
print list2

列表推导中的语句必须是单个语句,但您始终可以将其设为函数调用:

def foo(i):
    print i
    print i * 2
    return i
list2 = [foo(i) for i in list1]
于 2009-04-21T22:18:46.013 回答
3

正如 pjz 所说,您可以使用函数,因此在这里您可以使用闭包来跟踪计数器值:

# defines a closure to enclose the sum variable
def make_counter(init_value=0):
    sum = [init_value]
    def inc(x=0):
        sum[0] += x
        return sum[0]
    return inc

然后你用list1做你想做的事:

list1 = range(5)  # list1 = [0, 1, 2, 3, 4]

现在只有两行,我们得到 list2:

counter = make_counter(10)  # counter with initial value of 10
list2 = reduce(operator.add, ([counter(x), x] for x in list1))

最后,list2 包含:

[10, 0, 11, 1, 13, 2, 16, 3, 20, 4]

这就是您想要的,您可以在循环后通过一次调用获取计数器的值:

counter()  # value is 20

最后,你可以用任何你想要的操作来替换闭包,这里我们有一个增量,但这完全取决于你。另请注意,我们使用 reduce 来展平 list2,这个小技巧要求您在使用 reduce 调用该行之前导入运算符:

import operator
于 2009-07-22T16:33:03.463 回答
2

这是另一个问题的示例:

[i for i,x in enumerate(testlist) if x == 1]

枚举生成器返回一个进入 i,x 的 2 元组。

于 2009-04-21T22:20:33.637 回答
1

首先,您可能不想使用print. 它不返回任何内容,因此for如果您只想打印内容,请使用常规循环。您正在寻找的是:

>>> list1 = (1,2,3,4)
>>> list2 = [(i, i*2) for i in list1] # Notice the braces around both items
>>> print(list2)
[(1, 2), (2, 4), (3, 6), (4, 8)]
于 2009-04-21T22:18:18.587 回答
1

在列表理解中调用打印是一件奇怪的事情。如果您向我们展示了您想要的输出,而不仅仅是不起作用的代码,将会有所帮助。

这里有两个猜测给你。无论哪种方式,重要的一点是列表推导中的值语句必须是单个值。您不能一次插入多个项目。(如果这就是您要执行的操作,请跳至第二个示例。)

list1 = [1, 2, 3]
list2 = [(i, i*2, i) for i in list1]
# list2 = [(1, 2, 1), (2, 4, 2), (3, 6, 3)]

要获取平面列表:

list1 = [1, 2, 3]
tmp = [(i, i*2) for i in list1]
list2 = []
map(list2.extend, tmp)
# list2 = [1, 2, 1, 2, 4, 2, 3, 6, 3]

编辑:在列表理解的中间增加一个值仍然很奇怪。如果你真的需要这样做,你最好只编写一个常规的 for 循环,并在你去的时候附加值。在 Python 中,像这样的聪明几乎总是被贴上“unpythonic”的标签。如果你必须这样做,但你会在这样的论坛中得到无休止的抨击。;)

于 2009-04-21T22:25:15.560 回答
1

对于您编辑的示例:

currentValue += sum(list1)

或者:

for x in list1:
    currentValue += x

列表推导很棒,我喜欢它们,但是简陋的for循环并没有错,你不应该害怕使用它 :-)

编辑:“但是如果我想增加与收集的值不同的值怎么办?”

那么,你想增加什么?您拥有 python 的全部功能!

按 x 平方递增?

for x in list1:
    currentValue += x**2

增加 x 的某个函数及其在列表中的位置?

for i, x in enumerate(list1):
    currentValue += i*x
于 2009-04-21T23:46:55.800 回答
1

为什么要创建重复列表。似乎列表理解所做的只是对内容求和。

为什么不只是。

list2 = list(list1)   #this makes a copy
currentValue = sum(list2)
于 2009-04-24T06:02:04.653 回答
0

你不能做多个语句,但你可以做一个函数调用。要执行您在上面似乎想要的操作,您可以执行以下操作:

list1 = ...
list2 = [ (sum(list1[:i], i) for i in list1 ]

通常,由于列表推导是 python 的“功能”部分的一部分,因此您仅限于...函数。其他人建议您可以在必要时编写自己的函数,这也是一个有效的建议。

于 2009-04-21T22:36:57.607 回答