8
list_a = [2, 4, 3, 6, 3, 8, 5]

list comprehension is very useful.

list_b = [a**2 for a in list_a]

I want to know how to write a self-reference in the list comprehension.

For example:

list_c = [a**2 if i == 0 else a*2 + (itself[i-1]) for i, a in enumurate(list_a)]

how to write the part of itself[i-1]?

mkrieger1
  • 19,194
  • 5
  • 54
  • 65
  • 6
    What is `itself` supposed to be a reference to? The as-yet uncompleted list comprehension…?! – deceze Jan 11 '18 at 10:20
  • What makes you think that this is possible? – Andras Deak -- Слава Україні Jan 11 '18 at 10:20
  • @deceze `list_c` I guess.. – Ma0 Jan 11 '18 at 10:21
  • 6
    You cannot refer to things that **do not exist** yet. And `list_c` does not exist inside the list-comprehension that *creates it*. You have to go with a for-loop here or find a mathematical way to re-write your comprehension that only references objects that exist – Ma0 Jan 11 '18 at 10:23
  • 10
    People are mocking this question but it is perfectly reasonable, and I would go so far as to say that Python *should* allow self-referential list comprehensions-I'm sure there are reasons why this isn't supported, but a priori this seems like a perfectly reasonable feature to have in a language (Haskell, for example, supports this...). The snarky comments are unwarranted. – Ben Kushigian Jun 10 '18 at 18:32

3 Answers3

9

List comprehension is meant to be a compact expression for the most straightforward use cases. You cannot reference the list itself in list comprehension, for that just use a regular for-loop:

list_c = []
for i, a in enumerate(list_a):
    if i == 0:
        list_c.append(a ** 2)
    else:
        list_c.append(a * 2 + list_c[i-1])

You can also rewrite that loop in a more efficient way:

list_a_iterator = iter(list_a)
list_c = [next(list_a_iterator) ** 2]  # May raise StopIteration if list_a is empty
for item in list_a_iterator:
    list_c.append(item * 2 + list_c[-1])
Andrea Corbellini
  • 17,339
  • 3
  • 53
  • 69
2

You cannot reference a list before it is created. However, you can use this hacky reduce approach if you desperately want a one-liner:

list_c = reduce(lambda lst, a: lst + [lst[-1] + a**2], list_a, [0])[1:]

And in Python > 3.2, you can use itertools.accumulate:

from itertools import accumulate
list_c = list(accumulate(a**2 for a in list_a))
user2390182
  • 72,016
  • 6
  • 67
  • 89
  • Thank you! I don't know itertools. I will try to learn this library. – Hiroyuki Taniichi Jan 11 '18 at 11:01
  • Well, you can't reference it before it is created, but it is created at the *start* of the list comprehension. I'm even able to actually reference it and use it *during* the list comprehension. Implementing the OP's desired list comp: https://repl.it/repls/NoxiousWordyBracket#main.py (Yes, of course I know it's absolutely awful, just having some fun and making some point :-) – Stefan Pochmann Oct 02 '20 at 16:46
1

You can access list_a from your comprehension:

[a**2 if i == 0 else a*2 + list_a[i-1]**2 if i == 1 else a*2 + list_a[i-1]*2 for i, a in enumerate(list_a)]
zipa
  • 27,316
  • 6
  • 40
  • 58