Python: change global list inside function

First of all, I understand that I can use the global operator to access global variables. But somehow I managed to change the global list without global , as shown below:

 def func1(nums): nums = [4,5,6] nums = [1,2,3] func1(nums) print nums # print [1,2,3] def func2(nums): nums[0] = 4 nums[1] = 5 nums[2] = 6 nums = [1,2,3] func2(nums) print nums # print [4,5,6] 

After trying func2, I realized that I can always access the global list in a function if I specify an index:

 def func3(nums): nums[:] = [4,5,6] nums = [1,2,3] func3(nums) print nums # print [4,5,6] 

Is it because Python automatically tries to map a global variable if a function variable is used before the definition?

Thanks.

+6
source share
5 answers

I understand that I can use a global statement to access global variables

Your understanding is wrong. You can always access a global variable if you do not have a local variable with the same name. You only need the global operator when you are going to change the object referenced by the variable name. In your func2 you do not do this; you change only the contents of the object. nums still belongs to the same list.

+9
source

This is a concept based on mutable and immutable objects in Python. In your case, for example:

 a=[1,2] def myfn(): a=[3,4] print id(a) >>>id(a) 3065250924L >>>myfn() 3055359596 

It is clear that both are different objects. Now:

 a=[1,2] def myfn(): a[:] =[3,4] print id(a) >>>id(a) 3055358572 >>>myfn() 3055358572 

This means that it is the same variable used in the local and global scope.

+3
source

In this particular case, this is because list are mutable.

As a result, their use in the global namespace or even passing through a function means that they will be changed, because Python contains a reference to the mutable object, and not a copy of it.

If you try to do the same with tuple , this will not work, as they are immutable.

A way to avoid this is to provide a copy of the function list, not the list itself:

 func2(list[:]) 

At the same time, you can do this with the default arguments, where you can specify the default argument as [] , and if you then .append() something to it, this default argument permanently holds this element inside it for all future calls (unless you delete them in any way).

0
source
  • The 2 nums variables are different, and they point to the same object or two different objects, although they have the same name.
  • when you call func1(nums) means you are passing the link. Now 2 variable nums points to the same object. ( 2 variables, 1 object )
  • when you assign in func1 , the internal variable nums will point to a new object, the external object remains unchanged ( 2 variables, 2 objects )
  • and when you call print nums , then nums is an external variable,
0
source

There are two factors for this result:

  1. Variables are simply names that refer to objects
  2. List is mutable

In func1 , nums refers to a new object because a new list will be created. Therefore global nums not affected.

In func2 modification is applied to the passed object. So global nums changing. A new object was not created because list mutable.

link: https://docs.python.org/3/faq/programming.html#what-are-the-rules-for-local-and-global-variables-in-python

0
source

All Articles