Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
585 views
in Technique[技术] by (71.8m points)

compilation - Python local variable compile principle

def fun():  
    if False:
        x=3
    print(locals())
    print(x)
fun()

output and error message:

{}
---------------------------------------------------------------------------
UnboundLocalError                         Traceback (most recent call last)
<ipython-input-57-d9deb3063ae1> in <module>()
      4     print(locals())
      5     print(x)
----> 6 fun()

<ipython-input-57-d9deb3063ae1> in fun()
      3         x=3
      4     print(locals())
----> 5     print(x)
      6 fun()

UnboundLocalError: local variable 'x' referenced before assignment

I am wondering how the python interpreter works. Note that x=3 doesn't run at all, and it shouldn't be treated as a local variable, which means the error would be " name 'x' is not defined". But look into the code and the error message, it isn't the case. Could anybody explain the mechanism principle of the compilation of the python interpreter behind this situation?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

A name used in a function can have only one scope for the whole function body. The scope is determined at compile time (not when the function is run).

If there's an assignment to a name anywhere in the function (regardless of whether it will be run when the function is called), the compiler will treat that name as local to the function by default. You can use the global and nonlocal statements to explicitly tell it to use a different scope.

A special case is where a name is assigned to in one function's body, and accessed from another function that is defined within the first function. Such a variable will be put in a special closure cell that will be shared between the functions. The outer function will treat the variable like a local, while the inner function can only assign to it if it has a nonlocal statement for the name. Here's an example of a closure and a nonlocal statement:

def counter():
    val = 0
    def helper():
        nonlocal val
        val += 1
        return val
    return helper

In addition to the issue you're seeing, there's another sort of scope confusion that you may see:

x = 1
def foo():
   print(x)  # you might expect this to print the global x, but it raises an exception
   x = 2     # this assignment makes the compiler treat the name x as local to the function

In the foo function the name x is considered a local everywhere, even though the print call tries to use it before it has been assigned to in the local namespace.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...