1

I have different nested lists:

a = [[] for e in range(6)]
b = [[] for e in range(6)]
c = [[] for e in range(6)]

Given those lists have similar structure, is it possible to assign them simultaneously (in one line) ? I was thinking about something begining like this:

a, b, c = [[] for e in range(6)] ...?...

I'm using Python 3

1
  • 1
    If you would perform a = b = c = [[] for e in range(6)] you would let a, b and c refer to the same list. Commented Jan 4, 2018 at 12:14

4 Answers 4

6

Python has a mechanism to let multiple variables refer to the same object, with:

a = b = c = [[] for e in range(6)]

But you probably do not want that, since now a, b and c refer to the very same list. So if we append to a, then that change is also reflected in b and c.

We can however use iterable unpacking with:

a, b, c = [[[] for e in range(6)] for _ in range(3)]

So here we construct a list that contains three lists, and we then unpack that list in three variables, such that each variable obtains its own sublist.

Or in general, if you have a certain expression that needs to be evaluated n times, and then assigned to n variables, you can use:

x1, x2, xn = [<expr> for _ in range(n)]

Here <expr> should of course be replaced with a real expression, and variables xi with real variables.

Sign up to request clarification or add additional context in comments.

9 Comments

This answer is detailed and well explained. Thank you and all others for your prompt responses.
Mostly out of curiosity: are there any pros/cons when comparing your approach of iterable (packing/)unpacking vs the tuple (packing/)unpacking approach of @DeepSpace's answer? I'm not very well-versed in python myself, but I could suspect that the tuple approach would be to prefer as n is not a runtime property (as we must match number of iterables/tuple members with the typed variables to unpack to), is this a plausible argument?
@dfri: both are iterable unpacking (tuple unpacking is sometimes used, but same concept). The difference is that the source in this answer is a list, whereas that of DeepSpace is a generator. When running this 10M times, I get 21.73s for my approach, and 22.04 for DeepSpace's approach, some the difference is negligable.
Thanks for your reply; I'm mostly talking about semantics and intent, though. Since we have fixed number of sources to be unpacked, would one possibly like prefer tuple unpacking over "variable (although known fixed size) list" unpacking? I guess I'm trying to query whether this unpacking case is comparable (w.r.t. choice of approach based on showing intent/semantics) to the contrived case a, b = ('a', 'b') vs a, b = ['a', 'b'], where I would see the former preferred over the latter ((string, string) 2-tuple vs variable-sized list that happens to have only two string members).
Ah I now re-read your last comment once more, "The difference is that the source in this answer is a list, whereas that of DeepSpace is a generator."; I was treating the rhs of DeepSpace's approach as an actual tuple being unpacked, but it's not (it a generator); so no direct comparison to my contrived example. Thanks for your replies!
|
4

You can abuse generators and tuple unpacking:

a, b, c = ([[] for e in range(6)] for _ in range(3))

Let's make sure that a, b and c don't reference the same list:

a[0].append(1)
b[0].append(2)
c[0].append(3)
print(a)
print(b)
print(c)

#  [[1], [], [], [], [], []]
#  [[2], [], [], [], [], []]
#  [[3], [], [], [], [], []]

2 Comments

I prefer tuple unpacking over list unpacking.
@Androbin see my comments (and Willem's answers) to the accepted answer; this is not tuple unpacking as the rhs above is a generator (not a tuple; I made the same mistake). Although a, b, c = *([[] for e in range(6)] for _ in range(3)), would be tuple unpacking, but possible with a wasteful middle step (generator to tuple? or true tuple comprehension?). For the latter, I can't say.
0

Try deepcopy :

from copy import deepcopy
a = [[] for e in range(6)]

b=deepcopy(a)
c=deepcopy(a)

Why deep copy why not copy:

Here is reason:

if you do with simple copy then if you modify original it will modify the copied nested list because its shallow copy

from copy import deepcopy
a = [[] for e in range(6)]

b=a[:]
c=a[:]

for i in a:
    i.append(22)

print(a)

print(b,c)

output:

[[22], [22], [22], [22], [22], [22]]
[[22], [22], [22], [22], [22], [22]] [[22], [22], [22], [22], [22], [22]]

But with deepcopy :

from copy import deepcopy
a = [[] for e in range(6)]

b=deepcopy(a)
c=deepcopy(a)

for i in a:
    i.append(22)

print(a)

print(b,c)

output:

[[22], [22], [22], [22], [22], [22]]
[[], [], [], [], [], []] [[], [], [], [], [], []]

Comments

-1

What about copying the lists? Not very symmetrical, but it works...

a = [[] for e in range(6)]
b, c = a[:], a[:]
assert a == b and a == c and b == c

As @vaultah noted this is not a deep copy: the nested lists are shared:

a[2].append(1)
assert a == b and a == c and b == c

import copy
b, c = copy.deepcopy(a), copy.deepcopy(a)

a[2].append(1)
assert a != b and a != c and b == c

2 Comments

a, b, c will share the inner lists
To whoever upvoted this answer: do you understand what the comment above says?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.