简体   繁体   中英

Why doesn't the with block in Python need the global keyword?

I am using the with block to extract information from a file, and I am surprised that any variables declared in the with block are global. Shouldn't they be local to the with block, and shouldn't you need to use global myVar before changing global variables? After all, with defines a code block, right?

Python doesn't have block scopes. The with statement does not introduce a new scope; the body of the statement is still in the same scope that has the with statement.

Python has 4 kinds of scopes:

  1. The built-in scope, defining names available in any module without an explicit import .
  2. Global scopes, one per module.
  3. Non-local scopes
  4. Local scopes: defined by a function.

No other construct defines a new scope: not if statements, not for or while loops, not with statements, not try statements, not class statements. Only things that define new functions ( def statements, lambda expressions, and comprehensions) create new (local) scopes.

Every name first looks in the local scope (which may be the global scope if not inside a function definition), then in any non-local scopes (which may not exist, if a function is defined in the global scope, not another local scope), then the global scope, and finally in the built-in scope.


A non-local scope is just a scope that isn't the current local scope. For a module defined at the global scope, the closest enclosing non-local scope is the global scope.

But if a function is defined inside another function, then the closest enclosing non-local scope is the local scope in which the function is defined.

Functions can be nested fairly deeply, so there could be 0 or more additional local scopes between the current local scope and the global scope in which name lookups can occur. For example,

x1 = 'a'

def f1():
    x2 = 'b'
    def f2():
        x3 = 'c'
        def f3():
            x4 = 'd'
            print(x1 + x2 + x3 + x4)
        f3()
    f2()

f1()

The output of this mess would be abcd . When the argument to the print statement requires values for each of the four variables, each lookup starts in the local scope. Only a value for x4 is found there; the other lookups extend into the nearest enclosing non-local scope, that of f2 . A value for x3 is found there, so the lookup for x1 and x2 extend to the next non-local scope, that of f1 . x2 is found, so f1 extends another stop. Finally, a value for x1 is found in the global scope.

So a non-local scope isn't so much a special kind of scope, just a name for a scope that isn't local to the currently executing function. It will either be the local scope of an enclosing function or the global scope.

A with statement does not create a scope (like if, for and while do not create a scope either).

As a result, Python will analyze the code and see that you made an assignment in the with statement, and thus that will make the variable assignment.

Initialization before the with scope can be safer in the sense that after the with statement we can safely assume that the variable exists. If on the other hand the variable should be assigned in the with statement, not initializing it before the with statement actually results in an additional check: Python will error if somehow the assignment was skipped in the with statement.

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