python - 导入模块中的全局变量

标签 python python-3.x function

我有以下代码: one.py

import two as t 

t.test1()

t.test2()

two.py

class test_class():
    def __init__(self,arg):
        print("created obj name is {}".format(arg))
        self.name = arg

non_global ="initial global"

obj = test_class("test name")



def test1():
    print("\t in test 1")
    print (obj.name)
    global non_global # wont work without global keyword, value still refers to "initial value"
    print(non_global) # initial value
    obj.name = "changed"
    #non_global = "changed global"


def test2():
    print("\tin test 2")
    print(obj.name)
    print(non_global)

结果是:

created obj name is test name
         in test 1
test name
initial global
        in test 2
changed
changed global

如果我将 test1() 更改为:

def test1():
    print("\t in test 1")
    print (obj.name)
    #global non_global # wont work without global keyword, value still refers to "initial value"
    print(non_global) # initial value
    obj.name = "changed"
    non_global = "changed global"

我在打印行上收到错误UnboundLocalError:赋值前引用的局部变量“non_global”

如果我评论 non_global = "changed global" 错误就会消失。

我的问题是:

为什么这种情况发生在 non_global 而不是 obj 上?我使用的是python 3.5

最佳答案

区别基本上在于,non_global 是变量赋值,而 obj.name 是属性赋值。

函数内的变量赋值使该变量成为局部变量,并且由于 Python 不会在局部范围之外的任何地方查找它,因此 print(non_global) 失败,因为它不是尚未在该范围内定义。这适用于 global 语句,因为通过使用 global 您告诉 Python 不要将其视为局部变量,因此可以从全局范围获取其值。

在解析函数体时会决定变量是否转到局部变量,因此当在实际声明之前尝试使用它时,您将在运行时收到错误。

另一方面,

obj.name 基本上使用简单的 LEGB lookup 搜索 obj然后将 name 属性设置为指定值。

类似地,您也可以在函数体内更新全局可变数据结构(列表、字典等),而无需使用 global

除了 = 之外,*=+= 等增强赋值也会使变量成为局部变量。

a = []

def func1():
    a += ['foo']

def func2():
    a.extend(['bar'])

def func3():
    a[0] += 'spam'


func1()  # Fails with UnboundLocalError: local variable 'a' referenced before assignment

func2()  # works fine

func3()  # Also works fine because a[0] is not a variable. 
         # We are telling Python to look for `a` and fetch its 0th item
         # and concatenate 'spam' to it.

print(a) # prints ['barspam']

字节码反汇编还可以帮助您指出差异:

>>> import dis
>>> dis.dis(func1)
 45           0 LOAD_FAST                0 (a)
              3 LOAD_CONST               1 ('foo')  # Load a local variable name foo
              6 BUILD_LIST               1
              9 INPLACE_ADD
             10 STORE_FAST               0 (a)      # Store local variable named foo
             13 LOAD_CONST               0 (None)
             16 RETURN_VALUE
>>> dis.dis(func2)
 48           0 LOAD_GLOBAL              0 (a)      # Load from global scope
              3 LOAD_ATTR                1 (extend)
              6 LOAD_CONST               1 ('bar')
              9 BUILD_LIST               1
             12 CALL_FUNCTION            1
             15 POP_TOP
             16 LOAD_CONST               0 (None)
             19 RETURN_VALUE
>>> dis.dis(func3)
 51           0 LOAD_GLOBAL              0 (a)      # Load from global scope
              3 LOAD_CONST               1 (0)
              6 DUP_TOPX                 2
              9 BINARY_SUBSCR
             10 LOAD_CONST               2 ('spam')
             13 INPLACE_ADD
             14 ROT_THREE
             15 STORE_SUBSCR
             16 LOAD_CONST               0 (None)
             19 RETURN_VALUE

# Names of local variables or arguments of each function obtained through its code object
>>> func1.__code__.co_varnames
('a',)
>>> func2.__code__.co_varnames
()
>>> func3.__code__.co_varnames
()

相关:Why am I getting an UnboundLocalError when the variable has a value?

关于python - 导入模块中的全局变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45357838/

相关文章:

python - 将一个字典复制到另一个字典中

javascript - 使用 querySelector 在 for 循环中获取属性

r - 如何为R中的函数内的函数提供动态数量的参数?

python - Python 内存优化是如何工作的?

python - 如果没有 python 中的所有样板,从 QUiLoader 加载是否安全?

python-3.x - python : Unable to import TA-lib while it shows in the pip list

javascript - 选择时表单中的重复字段

python - 寻找附近 friend 的算法?

python - 为什么 Pandas 的速度如此之快?如何定义这样的功能?

python - 在python中将多个字典转换为单个字典