简体   繁体   中英

What happens when using 'global' keyword before defining inside a function?

I am a beginner in Python, just encountered 'global' keyword recently. I understand the basic usage that 'global' changes the scope of a variable, but I wonder why the following code doesn't work:

def foo():
    global y
    print('y inside foo is', y)

foo()
print('global y is', y)

I would assume it outputs some empty variable like None, however it gives:

NameError: name 'y' is not defined

I've tried:

def foo():
    global y
    y = 1
    print('y inside foo is', y)

foo()
print('global y is', y)

This gives:

y inside foo is 1
global y is 1

which is expected because we first declare there is a global variable y, and then assign 1 to it, so we find it in the globals().

Another side question is:

def foo():
    def bar():
        print(locals())
        print(y)
    y = 1
    bar()
foo()

gives:

{'y': 1}
1

because inside bar(), we have one local variable 'y'.

But the local variable 'y' just disappears when I change it to:

def foo():
    def bar():
        print(locals())
        y = y + 1
        print(y)
    y = 1
    bar()
foo()

print(locals()) outputs {}, I don't understand why.

You never define y to actually contain a value. In Python, trying to access a variable that has no value throws a NameError , which you are seeing here. You could initialize your variable to start (with None or some other preferred default value), and then use it through the rest of the file, like so:

y = None
def foo():
    global y
    print('y inside foo is', y)

foo()
print('global y is', y)

y inside foo is None
global y is None

example 1: What is an "empty variable" in Python? You never defined y ; you got smacked.

example 2: You understand

example 3: No, bar does not have a local variable y . Since there is none, it searches outward through its context stack, and finds y in the next name space, foo .

example 4: locals is, indeed, empty. y is local to foo , not to bar . However, your increment statement faults because the attempt to change y implies that you have either a global y (you do not), or you're defining a new one. Thus, the RHS y must be local -- but is as yet undefined, and you get smacked again.

Every thing happen when Python create the function it scans it's body:

def foo():
    def bar():
        print(locals())  # P is not present
        print(y)
        print(y)
        x = 5
        print(locals())  # after initializing x is added to local
    y = 1
    p = 1
    # ('x',) local variables
    print(bar.__code__.co_varnames)
    # ('y',)  non local variables used by the function
    print(bar.__code__.co_freevars)
    bar()
foo()

Python found that bar used y but it's not initialized in any point in the body function so it's co_freevars :

co_freevars: tuple of names of free variables (referenced via a function's closure

other variable that are are on left side of an assiegnment expression are co_varnames

co_varnames: tuple of names of arguments and local variables

When you use global you are telling Python that this is not a local variable, and when you change it's value you change it in the global space where the function is defined not where it's called.

def foo():
    global y  # assumes that y exist in the current module
    y = 5  # when you change it's value it change the value of y in the current module

# even that we used `y` in a left side of assignment expression is not added as local variable
print(foo.__code__.co_varnames)

when you define foo in a module that don't define a variable y , foo will not find that variable in the global scope of that module and this why you get: NameError: name 'y' is not defined .

To understand more the role global keyword check this:

def foo():
    global y
    y = 1  # this set the variable in the scope of module not the scope of this function
    print('y' in locals())  # False it's not a local variable of this method


print('y' in globals())  # False
foo()
print('y' in globals())   # True

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM