L.Jovi
L.Jovi

Reputation: 1761

python variable scope with only function

I don't understand why this code prints None in b():

# coding: utf-8                                                                               


saber = None
rider = dict()


def a():
    saber = 'ex'
    rider['a'] = 'b' 
    print saber
    print rider


def b():
    print saber
    print rider


if __name__ == '__main__':
    a() 
    b() 

When b() is called, printing saber results in None being printed. Why?

Upvotes: 4

Views: 136

Answers (5)

michaelgulak
michaelgulak

Reputation: 631

In a(), you are re-declaring saber locally, and so it references a local variable and not the global that you declared in the beginning of your code. See this documentation for more information. The solution is to declare saber global at the beginning of a():

def a():
    global saber
    saber = 'ex'
    rider['a'] = 'b' 
    print saber
    print rider

Upvotes: 6

Marcin
Marcin

Reputation: 239000

saber and rider are global, but in a() you have:

def a():
    saber = 'ex'     # local variable saber, rather than the global one
    rider['a'] = 'b' # global variable rider
    print saber
    print rider

Upvotes: 1

Óscar López
Óscar López

Reputation: 236170

Try this in a():

global saber
saber = 'ex'

See this post for a similar question. Basically, if you don't specify that saber is global, it'll be interpreted as local to the function. We don't have to do the same for rider because we're not actually reassigning it, only modifying its contents.

Upvotes: 5

Stephen Lin
Stephen Lin

Reputation: 4912

Check my comments in the code.

#!/usr/bin/python
# -*- coding: utf-8 -*-

saber = None
rider = dict()
# use id() to get memory address of this object
print id(saber)
print id(rider)



def a():
    saber = 'ex'
    rider['a'] = 'b'
    print id(saber)
    # as you can see here, you have created a new object inside function a which replace the global variable
    print saber
    print id(rider)
    # you are using the same object from global 
    print rider


def b():
    print id(saber)
    # you are using the global variable here
    print saber
    print id(rider)
    # you are using the global variable here
    print rider


if __name__ == '__main__':
    a()
    b()

OUTPUT:

35731224
506032968
35662984
ex
35731224
{'a': 'b'}
506032968
None
35731224
{'a': 'b'}

Upvotes: 3

kindall
kindall

Reputation: 184465

saber is None in b() because you have defined it as a global variable with a value of None and have not defined a local variable of the same name in that function. In a() you defined saber with a value of "ex" and when you printed that variable, that's what you got. But that value of saber went away when the function finished, because it is local to the function, and that's what local variables do.

Now you might ask why rider was changed in a() when saber was not. But in fact, rider was not changed. You did not assign to the name rider in a(), so the global variable rider was used. The contents of rider were changed (you added a new key/value pair) but rider itself is still the same dictionary object it was when you first defined it. And that's why when you print it in b() you get the changed dictionary. Both functions are using the global variable rider because there is no local variable of the same name "hiding" it.

Upvotes: 6

Related Questions