Python Forum

Full Version: Question regarding local and global variables
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Pages: 1 2
I'm relatively new to learning Python. I've been reading "Mastering Python". In chapter 2 on Variables it provides an example similar to this:
a = 20
b = 30
c = [1, 2, 3]

def demo():
    a = 21
    b = 31
    c = [4, 5, 6]
    
demo()
So after I run the program and do a print(a,b,c) I get the result as expected

>>> print(a,b,c)
20 30 [1, 2, 3]
So I somewhat understand the scope of variables in reference to global versus local. The variables outside of the def are global and within the def are local. So far so good. But what if I do this:

a = 20
b = 30
c = [1, 2, 3]

def demo():
    a = 21
    b = 31
    c[0] = 5
    
demo()
Now I get this result

>>> print(a,b,c)
20 30 [5, 2, 3]
So if declaring a or b to new values in the def object doesn't change them why does c[0] = 5 change the global list of c without declaring it global within the def object?

Sorry if this seems elemental but this really stuck out to me as I was thinking about some other code that I have been working with.

Thanks.
Don
Lists are mutable. It's the same object i.e. same id, but because lists sa mutable, the element at index 0 has changed.
c = [1, 2, 3]
print(id(c), c)
 
def demo():
    c[0] = 5
     
demo()
print(id(c), c)
Output:
139939046686920 [1, 2, 3] 139939046686920 [5, 2, 3]
Before you can subscript a variable, the variable must already exist. So when you do c[0] = 5, it first will search the local scope for c, and not finding it, will search the global scope for c.
If you did
c = [1, 2, 3]
print(id(c), c)
  
def demo():
    c = [1, 2, 3]
    c[0] = 5
      
demo()
print(id(c), c)
You will see that the global c is not changed as there is now a local version created.
(Apr-12-2020, 02:24 PM)TomToad Wrote: [ -> ]Before you can subscript a variable, the variable must already exist. So when you do c[0] = 5, it first will search the local scope for c, and not finding it, will search the global scope for c.

So in my example a&b already existed outside the object so why are they not found inside as is c ?
if in the local scope you try to assign to a name that is not being declared global, then it will be local (that is what happening in the first snippet)
In the second snippet you assign to a and b, so they again are local names. For c, you don't assign to c, you assign new value to element with index 0. That's the difference, you don't create new name c within the local scope, so it uses the one from the global scope. see the difference

a = 20
b = 30
c = [1, 2, 3]
print(f'outside, id: {id(c)}, c:{c}')
def demo():
    a = 21
    b = 31
    c = [4, 5, 6]
    print(f'inside, id: {id(c)}, c:{c}')
    c[0] = 7
    print(f'inside, id: {id(c)}, c:{c}')
     
demo()
print(f'outside, id: {id(c)}, c:{c}')
Output:
outside, id: 139836028387528, c:[1, 2, 3] inside, id: 139836028387592, c:[4, 5, 6] inside, id: 139836028387592, c:[7, 5, 6] outside, id: 139836028387528, c:[1, 2, 3]
So if I do this I see the inside and outside id of a & b are different even though I declared a & b global inside.

a = 20
b = 30
c = [1, 2, 3]
print(id(a),a, id(b),b, id(c),c)

def demo():
    global a
    global b
    a = 21
    b = 31
    c[0] = 5
    print(id(a),a, id(b),b, id(c),c)
    
demo()

>>> %Run test1.py
4428144000 20 4428144320 30 4435940048 [1, 2, 3]
4428144032 21 4428144352 31 4435940048 [5, 2, 3]
names in python are just pointers, at the beginning name a points to an int object - 20 with id 4428144000
after you call the function name a points to different int object - 12 (i.e. different location in memory, thus different id 4428144032)
as you can see c is pointing to same object, although element at index 0 has changed (which is possible, because lists are mutable objects).

Read this https://nedbatchelder.com/text/names1.html

also
a = 5
b = 5
print(id(a), id(b))
Output:
11381600 11381600
(Apr-12-2020, 02:44 PM)donmerch Wrote: [ -> ]So if I do this I see the inside and outside id of a & b are different even though I declared a & b global inside.

That is a good question. If you print the values again after demo() is called, you will see that the main values do change when assigned from within the function. But curiously, the ids are overwritten as well which seems to contradict the documentation.
a = 20
b = 30
c = [1, 2, 3]
print("before demo()",id(a),a, id(b),b, id(c),c)
 
def demo():
    global a
    global b
    a = 21
    b = 31
    c[0] = 5
    print("In demo()",id(a),a, id(b),b, id(c),c)
     
demo()
print("After demo()",id(a),a,id(b),b,id(c),c)
Output:
before demo() 140724845310816 20 140724845311136 30 1546429675272 [1, 2, 3] In demo() 140724845310848 21 140724845311168 31 1546429675272 [5, 2, 3] After demo() 140724845310848 21 140724845311168 31 1546429675272 [5, 2, 3]
Quote:id(object)
Return the “identity” of an object. This is an integer which is guaranteed to be unique and constant for this object during its lifetime. Two objects with non-overlapping lifetimes may have the same id() value.

The output does not show a unique and constant id.
Maybe also read this:
https://docs.python.org/3/faq/programmin...-in-python

Quote:What are the rules for local and global variables in Python?

In Python, variables that are only referenced inside a function are implicitly global. If a variable is assigned a value anywhere within the function’s body, it’s assumed to be a local unless explicitly declared as global.

Though a bit surprising at first, a moment’s consideration explains this. On one hand, requiring global for assigned variables provides a bar against unintended side-effects. On the other hand, if global was required for all global references, you’d be using global all the time. You’d have to declare as global every reference to a built-in function or to a component of an imported module. This clutter would defeat the usefulness of the global declaration for identifying side-effects.
Ok thanks all for your explanations. I have a lot more to learn obviously. It just stood out to me why one type of object (integer, list) is referred to differently inside and outside a function.
Pages: 1 2