开发者

Confusion about Python variable scope

开发者 https://www.devze.com 2023-02-14 11:29 出处:网络
I came across some code which kind of puzzled me. Here\'s a minimal example which shows this: # of course, the ... are not part of the actual code

I came across some code which kind of puzzled me. Here's a minimal example which shows this:

# of course, the ... are not part of the actual code
some_var = {"key1":"value1" ... "keyN":"valueN"}

def some_func():
   v = some_var["key1"]

The code works, but the fact that I can access some_var directly confuses me. The last time I had to write some Python code, I remember having to write some_func like this:

def some_func():
   global some_var
   v = some_var["key1"]

I am using Python 2.7.1 on a Windows 7 PC. Did something change in the 2.7 release tha开发者_JAVA百科t allows for this?


No, you just can't reassign some_var in a local scope. Consider the following:

some_var = {}
def some_func():
    # some_var[5] = 6
    some_var = {1:2}
    some_var[3] = 4
some_func()
print (repr(some_var)) # {}

You'll see the assignment in some_func actually creates a local variable which shadows the global one. Therefore, uncommenting the line would result in an UnboundLocalError - you can't access variables before they're defined.


There's a difference between using (e.g. calling or using in an expression) a name from an outer scope and assigning it (and there's a difference between assigning a bare variable and assigning a member of an object pointed to by a variable - x.y = ... and x[...] = ... count as method calls!).

You only need to declare that a variable is from an outer scope if you're re-assigning it. In Python 2, you can only do that with global variables (via global var), in Python 3 you can do it for abritarily nested scopes (e.g. closures) using nonlocal var.

Using a nonlocal variable as in you example doesn't require global. It does, however, as soon as you assign the variable (with the aforementioned definition of assignment) anywhere within that scope - so add a line some_var = ... after the line where you're using it and you'll get an UnboundLocalError. Refer to the documentation for the nitty gritty details.


You only have to use global if you want to assign a new value to that variable.

Nested scope was introduced in Python 2.1 (and enabled by default in Python 2.2) (emphasis mine):

Put simply, when a given variable name is not assigned a value within a function (by an assignment, or the def, class, or import statements), references to the variable will be looked up in the local namespace of the enclosing scope. A more detailed explanation of the rules, and a dissection of the implementation, can be found in the PEP.


You only need to use global if you intend to assign to the variable, for reading the variable this is not necessary. This difference is not arbitrary, though it may seem like it at first glance.

When reading a value the interpreter can just look for a local variable named some_var, if it cannot find it then it looks for a global variable of that name. These are simple and straight forward semantics.

When assigning values to a variable the interpreter needs to know whether you intend to assign to a local variable some_var or a global variable. The interpreter assumes that some_var = 2 when called within a function is assigning to a local variable, this makes sense since this is the most common case. For the relatively rare times when you want to assign to a global variable from within a function then you use the global modifier global some_var = 2.


It depends on the usage of the variable in the function Python variable scope error


Assigning a value to a name makes the name local, unless the name is explicitly declared global.

a = 12

def foo():
   a = 42
   print a   # uses local

foo()
>>> 42

def foo():
   global a
   a = 42

foo()
print a
>>> 42

If a name is not assigned to, it is global.

a = 12

def foo():
   print a   # uses global

foo()
>>> 12

In short, you only have to explicitly declare a name global if you will be assigning to it. If you are just reading from it, you can use it at will. However, if you ever assign to the variable, it will be considered local in that function unless you declared it global.

b = 5

def foo():
   print b
   b = 7

foo()
>>> ???

Since b is assigned to in foo() and not declared global, Python decides at compile time that b is a local name. Therefore b is a local name throughout the whole function, including at the print statement before the assignment.

Therefore the print statement gives you an error, because the local name b has not been defined!

0

精彩评论

暂无评论...
验证码 换一张
取 消