Why when list can be the global level but variable has to be addressed

Hi all,

I have reviewed the answers above, but I still have some question regarding this.
Can someone tell me why when list can be the global level but variable has to be addressed in this case?
This works:

lst=[]
x = 0
def divisible_by_ten(nums):
    x = 0
    for i in nums:
        if i % 10 == 0:
            lst.append(i)
            x+=1
    return len(lst)


#But not this one:


x =0

def divisible_by_ten(nums):

  for i in nums:

    if i % 10==0:

      x+=0

  return x

In your first example, x has been declared in function block scope. The x that is declared globally is shadowed by this variable. They are not the same variable.

Consider,

>>> def foo():
	a = 6 * 7
	return a, id(a)

>>> a = 42
>>> id(a)
140732528053184
>>> foo()
(42, 140732528053184)
>>> 

The above is deceiving because it is not looking at the variables, but the values. Since they are the same, they have the same id. There is only one value in memory, and they both point to it.

Now consider,

>>> def foo():
	a = 6 * 7
	print (a, id(a))

	
>>> a = 6 + 7
>>> foo()
42 140732528053184
>>> a, id(a)
(13, 140732528052256)
>>> 

The id is different because the values differ; the values are different because the variables have differing scope.

Now let’s look at the other variable. It is a list object which is accessible from everywhere. Inside a function if we don’t shadow the variable (not giving it a new value), we can make changes to elements in the global list object. Your example is mutating that list. This is permitted. Now remove the x = 0 line from the function code and try to run it.

It should have raised an exception, x is not locally defined, or some such. In fact it is not defined in terms of assignment, though we can access it to read. We cannot assign a value to a global variable that is not a data structure, such as list, dict or set. This is why we could mutate the list, but not add 1 to x.

Consider,

>>> a = []
>>> def foo():
	a.append(6 * 7)
	print (a, id(a))

	
>>> id(a)
1602677826816
>>> a
[]
>>> foo()
[42] 1602677826816
>>> a
[42]
>>> 

Going back to the values having their own id,

>>> id(a[0])
140732528053184
>>> 

Compare this to the earlier example, above.

Disclaimer

This is demonstration code in order to illustrate the inner workings. It is not necessarily recommended code. If we did not declare a as a list above, it would likely have raised an error.

We avoid this problem by setting a parameter in the function.

>>> def foo(a):
   a.append(6 * 7)
   print (a, id(a))

   
>>> b = []
>>> foo(b)
[42] 1602678207744
>>> b
[42]
>>> 

Now think on this…

>>> c = [b]
>>> foo(c)
[[42], 42] 1602678503744
>>> b
[42]
>>> c
[[42], 42]
>>> b[0] = 89
>>> c
[[89], 42]
>>>