8

First of all, I understand that I can use global statement to access global variables. But somehow I was able to modify a global list without global like 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 global list in a function if I specify the 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 goes trying to match a global variable if a function variable is used before definition?

wjandrea
  • 28,235
  • 9
  • 60
  • 81
Yuhao Zhang
  • 470
  • 2
  • 4
  • 13
  • What exactly is your question? `nums = ` is a local assignment, unrelated to the outer scope, whereas in the other cases you're modifying the same object. – jonrsharpe Jul 15 '15 at 16:12
  • Does this answer your question? [In Python, why is list\[\] automatically global?](https://stackoverflow.com/questions/6329499/in-python-why-is-list-automatically-global) – user202729 Feb 22 '21 at 03:22

5 Answers5

13

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

Your understanding is wrong. You can always access a global variable as long as you don't have a local variable of the same name. You only need the global statement when you are going to change what object a variable name refers to. In your func2, you are not doing that; you are only changing the contents of the object. nums still refers to the same list.

kindall
  • 178,883
  • 35
  • 278
  • 309
3

It is of 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 both are different objects. Now:

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

>>>id(a)
3055358572
>>>myfn()
3055358572

That means it is same variable using in local and global scope.

jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
itzMEonTV
  • 19,851
  • 4
  • 39
  • 49
  • 1
    That has nothing to do with mutability. It's a matter of mutating a value vs rebinding the value of a variable. – Aran-Fey Aug 12 '18 at 12:26
2

In this specific case it is because lists are mutable.

As a result having them in the global namespace, or even passed through a function, means that they will be changed as Python holds the reference to the mutable object, not a copy of it.

If you try the same thing with tuples it will not work, as they are immutable.

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

func2(list[:])

At the same time you can do this with default arguments, where you can specify a default argument to be [], and if you then .append() something to it, that default argument will forever hold that item within it for all future calls (unless you remove it in some way).

jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
NDevox
  • 4,056
  • 4
  • 21
  • 36
0
  • 2 variables nums are different and they point to a same object or 2 different objects, though they have same name.
  • when you call func1(nums), mean that you pass a reference. Now the 2 variable nums point to same object. (2 variables, 1 object)
  • when you assign in func1, the inside variable nums will point to a new object, the outside is still unchanged (2 variables, 2 object)
  • and when you call print nums then this nums is the outside variable,
Hùng Ng Vi
  • 1,251
  • 2
  • 14
  • 20
0

There are two reasons for this result:

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

In func1,nums refer to a new object because a new list is created. Therefore global nums is not affected.

In func2, the modification is applied to the object passed in. Thus global nums is changed. A new object is not created because list is mutable.

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

BlueBlue
  • 1
  • 1