Python函数作用域导入

Ric*_*kyA 1 python python-import

我有以下模块:

main.py

import my_import

my_import.a_func()
Run Code Online (Sandbox Code Playgroud)

my_import.py

FOO = "foo"
BAR = []

def a_func():
   BAR.append("bar") #ok
   FOO = FOO + "foo" #UnboundLocalError: 
                     #local variable 'FOO' referenced before assignment
Run Code Online (Sandbox Code Playgroud)

这可能是由于进口,但如何?

[编辑]

从我得到的答案不是导入是crulpit,但后续仍然是奇怪的:

FOO = "foo"
BAR = []
def a_func():
    BAR.append("bar")
    print(FOO)
a_func()
Run Code Online (Sandbox Code Playgroud)

- >打印"foo"

FOO = "foo"
BAR = []
def a_func():
    BAR.append("bar")
    print(FOO)
    FOO = FOO + "foo"    
a_func()
Run Code Online (Sandbox Code Playgroud)

- >失败,"UnboundLocalError:赋值前引用的局部变量'FOO'"并且不打印"foo"

看起来解释器在实际运行代码之前正在查找当前作用域中的赋值.

unu*_*tbu 5

当Python解析函数定义时,它会记录赋值语句左侧的所有变量名,例如

FOO = FOO + "foo"
Run Code Online (Sandbox Code Playgroud)

它将所有这些变量名称注册为局部变量.

让我强调一下,赋值语句使Python FOO解析函数定义时注册为局部变量,而不是在调用函数时注册.所以稍后,当调用该函数时,即使对该函数的引用FOO发生在赋值之前仍然引用局部变量并且可以引发该函数UnboundLocalError.

def a_func():
    BAR.append("bar")
    print(FOO)       #<--- "Freaky" UnboundLocalError occurs here!
    FOO = FOO + "foo" 
Run Code Online (Sandbox Code Playgroud)

所以在里面a_func,FOO是一个局部变量.在没有print(FOO)语句的情况下,Python到达赋值并且它首先评估右侧.它遇到变量名称,FOO将其识别为局部变量并询问它的值是什么?它没有价值!所以它提出了一个UnboundLocalError.

要修复,请使用global FOO声明FOO内部a_func引用全局变量:

FOO = "foo"
BAR = []

def a_func():
   global FOO
   BAR.append("bar") #ok
   FOO = FOO + "foo" assignment
Run Code Online (Sandbox Code Playgroud)

相比之下,BAR.append('bar')因为Python首先查找变量而起作用BAR- 它不认为它是局部变量,因为没有赋值形式BAR = ....它BAR在全局范围内找到,然后查找其append方法,然后进行变异BAR.因此你可以改变BAR但不能分配FOO(没有global FOO语句.)