Why in Python a list self-reference doesn't behave the same way when extended or summed?

Viewed 70

This is just a theoretical question and doesn't have any use case I believe.

I was playing with lists self reference and I noticed that:

 >>> l = []                                                                                                                                        
 >>> l.append(l)                                                                                                                                   
 >>> l.append(l)                                                                                                                                   
 >>> l                                                                                                                                             
 [[...], [...]]                                                                                                                                     
 >>> l+l                                                                                                                                           
 [[[...], [...]], [[...], [...]], [[...], [...]], [[...], [...]]]   

And ok the output seems fine? Then I tried:

 >>> l = []                                                                                                                                        
 >>> l.append(l)                                                                                                                                   
 >>> l.append(l)                                                                                                                                   
 >>> l                                                                                                                                             
 [[...], [...]]                                                                                                                                    
 >>> l.extend(l)                                                                                                                                   
 >>> l                                                                                                                                             
 [[...], [...], [...], [...]]

I thought l+l and l.extend(l) would behave the same way with the only difference that list+list creates a copy

I then checked references but they are all the same:

 >>> l = [] 
 >>> l.append(l) 
 >>> l.append(l) 
 >>> l 
 [[...], [...]] 
 >>> l+l 
 [[[...], [...]], [[...], [...]], [[...], [...]], [[...], [...]]] 
 >>> e =l+l 
 >>> e[0][0] is e[0][1] 
 True 
 >>> e[0][0] is e[0] 
 True 
 >>> e[0] is e[1] 
 True

TLDR Why

>>> l+l                                                                                                                                           
 [[[...], [...]], [[...], [...]], [[...], [...]], [[...], [...]]]   

But

 >>> l.extend(l)                                                                                                                                   
 >>> l                                                                                                                                             
 [[...], [...], [...], [...]]
1 Answers

The recursive __repr__ for builtin objects checks for the first recursion and prints it.

In case of .extend() you take the list of 2 lists, and turn them into a list of 4 lists:

             1
  1.1    1.2    1.3    1.4
[[...], [...], [...], [...]]

Since each list is itself and prints the same, the recursion ends here.

In case of the +, the output object is not the same as the other lists:

                               unique
       1               2               3                4
   1.1    1.2      2.1    2.2      3.1    3.2      4.1    4.2
[[[...], [...]], [[...], [...]], [[...], [...]], [[...], [...]]]  

You have one outer list of 4, BUT, each sub list contains 2 items. The recursion only starts when you go into depth 2.

Basically, in the first one 1.1 == 1 but in the second one 1 != unique.

Related