1

Am trying to create a multidimensional list. Input would be:

L1 = [2,3,4]
L2 = [5,6,7]

Output would be x ** y, where x is from L1 and x is from L2

L3 = [[32,64,128],[243,729,2187],[1024,4096,16384]]

My code is as below:

L1 = [2,3,4]
L2 = [5,6,7]

L3 = [[None] * len(L1)] * len(L2)
c=0
for x in L1:
    d=0
    for y in L2:
        L3[c][d] = x ** y
        d = d+1
    c = c+1

print L3

Here the output is :

[[1024,4096,16384],[1024,4096,16384],[1024,4096,16384]]

While debugging i got to know:

at the time of assigning to "L3[0][0]" , its assigning values to L3[0][0],L3[1][0],L3[2][0]. It should assign nine times. During each assignment its assigning to 3 places. I am not getting how its working.

I tried to print

id(L3[0])
id(L3[1])
id(L3[2])

and all are printing same memory location address.

Is it because of the same memory address that the value is passed to 3 places at once(the value of x**y is simultaneously going to L3[0][0],L3[1][0],L3[2][0]?

Can somebody help me out of this.

Thanks in advance, SRP

s.patra
  • 147
  • 1
  • 9
  • `*` copies by reference, so changing the first element changes all of the others. – Akshat Mahajan Sep 07 '16 at 18:04
  • @akshat.....if we try to make L3 a single dimensional list with [None] * (Len(L1) * Len(L2)) and try to assign things then it works fine means it stores all results properly in one dimensional list L3. During creating one dimensional list also copies by reference happens. Then how it works? – s.patra Sep 07 '16 at 19:08
  • `None` - like integers, strings and other primitives - is an immutable type. `*` applied to immutable types results in copying by value, because copying by reference defaults to that for immutable types. The same does not hold for `[None]`, because now you have a mutable type - a list - so `*` copies by reference. – Akshat Mahajan Sep 07 '16 at 19:11
  • What I understand from your explanation is that when I write [None] * (Len(L1)*Len(L2)) , its creating copy by value. But I tried to print id(L3) for all 9 contents and it displays the same memory. – s.patra Sep 08 '16 at 06:45
  • 1
    No, when you do _that_, it's copy by reference. When you do just `None * 5`, that's copy by value. When you do `[None] * 5`, that is copy by reference. There is a difference between a None primitive and a list containing a None primitive. – Akshat Mahajan Sep 08 '16 at 06:48
  • OK. Now I have created a list like [None] * 5. It will be [None,None,None,None,None]. It's copy by reference. All the contents(None) have same memory address. When something is assigned to L3[0], it is not assigned to all through the list but only to ist place. But in case of copy by reference it should be assigned to all, as it is happening in my code posted above. Plz correct me if am wrong. – s.patra Sep 08 '16 at 09:33
  • My apologies - I meant `[[None]] * 5` is copy by reference and `[None] * 5` will be copy by value. There's an extra set of square brackets that I didn't type out in my earlier comments, on the premise that I thought I was being clear we were referencing sublists. Try this: `s = [[None]] * 5; s[1][0] = 3` - this will change the content of all the sublists. – Akshat Mahajan Sep 08 '16 at 19:25

2 Answers2

3

Maybe this is what you want?

[[x**y for y in L2] for x in L1]

[[32, 64, 128], [243, 729, 2187], [1024, 4096, 16384]]

Alex
  • 41,580
  • 88
  • 260
  • 469
0

Here is what i would do

L1 = [2,3,4]
L2 = [5,6,7]
L3 = []
for x in L1:
    tmp = []
    for y in L2:
        tmp.append(x ** y)
    L3.append(tmp)

print L3

[[32, 64, 128], [243, 729, 2187], [1024, 4096, 16384]]

supamaze
  • 8,169
  • 2
  • 11
  • 11