Multiple statements in list compherensions in Python?

后端 未结 9 1419
不思量自难忘°
不思量自难忘° 2021-02-13 07:09

Is it possible to have something like:

list1 = ...

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

I tried that but didn\'t wor

相关标签:
9条回答
  • 2021-02-13 07:47

    As pjz said, you can use functions, so here you can use a closure to keep track of the counter value:

    # 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
    

    Then you do what you want with list1:

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

    And now with just two lines, we get list2:

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

    In the end, list2 contains:

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

    which is what you wanted, and you can get the value of the counter after the loop with one call:

    counter()  # value is 20
    

    Finally, you can replace the closure stuff by any kind of operation you want, here we have an increment, but it's really up to you. Note also that we use a reduce to flatten list2, and this little trick requires you to import operator before calling the line with the reduce:

    import operator
    
    0 讨论(0)
  • 2021-02-13 07:48

    Why would you create a duplicate list. It seems like all that list comprehension would do is just sum the contents.

    Why not just.

    list2 = list(list1)   #this makes a copy
    currentValue = sum(list2)
    
    0 讨论(0)
  • 2021-02-13 07:52

    First of all, you likely don't want to use print. It doesn't return anything, so use a conventional for loop if you just want to print out stuff. What you are looking for is:

    >>> 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)]
    
    0 讨论(0)
  • 2021-02-13 08:01

    Statements cannot go inside of expressions in Python; it was a complication that was deliberately designed out of the language. For this problem, try using a complication that did make it into the language: generators. Watch:

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

    The generator keeps a running tally of the items seen so far, and prefixes it to each item, just like it looks like you example tries to do. Of course, a straightforward loop might be even simpler, that creates an empty list at the top and just calls append() a lot! :-)

    0 讨论(0)
  • 2021-02-13 08:03

    Print is a weird thing to call in a list comprehension. It'd help if you showed us what output you want, not just the code that doesn't work.

    Here are two guesses for you. Either way, the important point is that the value statement in a list comprehension has to be a single value. You can't insert multiple items all at once. (If that's what you're trying to do, skip to the 2nd example.)

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

    To get a flat list:

    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]
    

    Edit: Incrementing a value in the middle of the list comprehension is still weird. If you really need to do it, you're better off just writing a regular for loop, and appending values as you go. In Python, cleverness like that is almost always branded as "unpythonic." Do it if you must, but you will get no end of flak in forums like this. ;)

    0 讨论(0)
  • 2021-02-13 08:03

    Here's an example from another question:

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

    the enumerate generator returns a 2-tuple which goes into i,x.

    0 讨论(0)
提交回复
热议问题