Python: encode list of list and assign value inside loop

I have the following code, why does the first not change alist , and the second change it?

 alist = [[1,2], [3,4], [5,6]] for item in alist: item = 1 print(alist) alist = [[1,2], [3,4], [5,6]] for item in alist: item = item.append(10) print(alist) 
+5
source share
7 answers

This is a somewhat unintuitive behavior of variables. This is because in Python, variables always refer to values.

Boxes and tags

In some languages, we tend to think of variables as “boxes,” where we put values; in Python, however, they are links and behave like tags or "aliases" to values. So, when you assign 1 to item , you only change the reference to the variable, not the list that it points to.

A graphical representation may help. Below is the list created by alist = [[1,2], [3,4], [5,6]]

List with three sublists

Given this, let's see what happens when we complete your first cycle.

First cycle

When you perform for item in alist , you ask the translator to take each value from the list, one at a time, put it in the item variable and perform some operation on it. In the first operation, for example, we have this new scheme:

Now the variable points to a sublist

Please note that we do not copy subscriptions to item ; instead, we point to it through item . Then do item = 1 - but what does that mean? This means that we are doing item on a value of 1 instead of pointing to a sublist:

item points to another value now

Note that the old link is lost (this is a red arrow), and now we have a new one. But we just changed the variable pointing to the list — we did not change the list itself.

Then we enter the second iteration of the loop, and now item points to the second sublist:

clause pointing to the second subscription

When we execute item = 1 , again, we just make the point variable for the aonther value without changing the list:

enter image description here

Now, what happens when we execute the second cycle?

Second cycle

The second cycle begins as the first: we make item link to the first subscription:

Now the variable points to a sublist

The first difference, however, is what we call item.append() . append() is a method, so it can change the value of the object that it calls. As we say, we send a message to the object pointed to by item to add the value 10. In this case, the operation is not performed in the variable item , but directly in the object to which it refers! So here is the result of calling item.append() :

List has grown

However, we are not only adding the value to the list! We also assign the value returned by item.append() . This will break the item link to the sublist, but here's the catch: append() returns None .

enter image description here

Value None

None is a value that basically represents the unavailability of the corresponding value. When a function returns None , it says most of the time: "I have nothing important to get you back." append() changes its list directly, so it has nothing to return.

This is important because you probably thought that item would point to an added list [1, 2, 10] , right? No, now he points to None . So, you expect the code below ...

 alist = [[1,2], [3,4], [5,6]] for item in alist: item = item.append(10) print(item) 

To print something like this:

 [1, 2, 10] [3, 4, 10] [5, 6, 10] 

But this does not happen. Here's what happens:

 >>> alist = [[1,2], [3,4], [5,6]] >>> for item in alist: ... item = item.append(10) ... print(item) ... None None None 

However, as we commented, the append() method changed the lists themselves. So, while the item variable was useless after the assignment, the final list was changed!

 >>> print alist [[1, 2, 10], [3, 4, 10], [5, 6, 10]] 

If you want to use the added list inside the loop, just don’t assign the return value of the item method. Do it:

 >>> alist = [[1,2], [3,4], [5,6]] >>> for item in alist: ... item.append(10) ... print item ... [1, 2, 10] [3, 4, 10] [5, 6, 10] 

This works because item will still point to a list.

Conclusion

The links are somewhat complicated to understand at first, not to mention dominance. However, they are really effective and can be studied if you follow the examples, etc. Your example is a bit more complicated because more is going on here.

A Python mentor can help you understand what is happening because it performs each step graphically. Check your own code there!

+5
source

In the first example, item bound to each element in the alist list, and then item returned as an integer 1 . This does not change the list item - it just renames the name item to an int 1 object.

In the second example, the list item (the list itself) is mutated using append() . item is still attached to the sub-list, so item.append() mutates the sub-list.

+4
source

Do you list.append() that list.append() does not return the list itself, but actually modifies the list in place?

item = 1 does as expected. For the rest of the for-loop elements, the element is now 1 , not the list that it was originally. This will not lead to reassignment of the fact that item is not what is needed for loops.

However, in the second loop, you now assign item = None , because the append function returns nothing, but adds the item to the list:

 >>> L = [1, 2, 3] >>> L.append(4) >>> L [1, 2, 3, 4] 

So your code basically says: "Go through each sublist in my main list and add 10 to it."

+2
source

The = operator does not make any changes to the second code, using .append causes changes to alist . Use the following line as the third line in the second code. You will see the same result:

 item.append(10) 

In the first item code, specify another object at item=1 , so alist does not change. In the second code, you make changes to alist by calling the append method.

+2
source

Pointer variable in python.

First example:

 for item in alist: item = 1 

each element points to every _item in alist, but suddenly you change the value of the element, not the _item value in alist, as a result, nothing changes to alist

Second example:

 for item in alist: item = item.append(10) 

each element points to each _item in the alist, and then you add something to the element using the same _item memory location, since the value of the _item value in alist changes as well as alist changes.

+2
source

Link document :

In the for-loop, variables are assigned in the target list. This overwrites all previous assignments to those variables, including those made in the for-loop set:

 for i in range(10): print(i) i = 5 # this will not affect the for-loop # because i will be overwritten with the next # index in the range 

So your second example is identical:

 alist = [[1,2], [3,4], [5,6]] for item in alist: item.append(10) # this statement modifies each item in alist # , which is what item the variable "points to" print(alist) 

That is, item is a new variable at each iteration . As a result, assigning values ​​to it in any particular iteration is meaningless, because its value will be redefined by reference to the next element in alist at the very beginning of the next iteration.

+1
source

When you write

 for item in alist: 

In fact, you create a copy of each element in liast in the variable item , and you do not get a link to item .

However, append modifies the list in place and does not return the value, and why you get the values ​​changed to None (due to the purpose - if you delete it, you will get a working fine added).

0
source

Source: https://habr.com/ru/post/1257923/


All Articles