Python 如何修改全局变量?

Python 如何修改全局变量?,python,globals,Python,Globals,下面是更新全局变量问题的简化版本- 在test.py中,我有: k1 = 1 def set_v(k, v): if k in globals(): globals()[k] = v; read_v() def read_v(): print("after {}".format(k1)) 执行以下操作后,代码将从python解释器运行: from test.py import * 产量 >>k1 1. >>>集合v('k1',2) 2点以后 >>>集合v('k1'

下面是更新全局变量问题的简化版本- 在
test.py
中,我有:

k1 = 1

def set_v(k, v):
  if k in globals():
    globals()[k] = v;
    read_v()

def read_v():
  print("after {}".format(k1))
执行以下操作后,代码将从python解释器运行:

from test.py import *
产量

>>k1
1.
>>>集合v('k1',2)
2点以后
>>>集合v('k1',3)
三点以后
>>>k1
1.
我搞不懂这个。
k1
具有全局作用域,因为
read_v()
在全局
dict
中看到它。 为什么对解释器可见的全局
k1
没有被更改?
我已经尝试过
setattr(module,var,val)
…但这与此没有什么不同。

当您从测试导入中执行
时*
会将所有这些对象和函数带到您的命名空间中。您有一个对
k1
的引用,
test
也有一个对
k1
的引用。但参考文献不一样。他们是不同的

试试这个:

>>> import test
>>> from test import *
>>> set_v('k1', 3)
after 3
>>> k1
1
>>> test.k1
3
修改
set_v
函数以同时打印出id。您将看到
test
k1
和导入REPL会话的
k1
是不同的


结论:每个版本的
k1
都驻留在各自的名称空间中。

当您从test import*执行
操作时,您会将所有这些对象和函数带到名称空间中。您有一个对
k1
的引用,
test
也有一个对
k1
的引用。但参考文献不一样。他们是不同的

试试这个:

>>> import test
>>> from test import *
>>> set_v('k1', 3)
after 3
>>> k1
1
>>> test.k1
3
修改
set_v
函数以同时打印出id。您将看到
test
k1
和导入REPL会话的
k1
是不同的


结论:每个版本的
k1
都驻留在各自的名称空间中。

Python中的Globals只在一个模块中是全局的

如果要修改导入模块中的全局变量,需要使用
module.variable
访问它

在测试的上下文中,这意味着:

import test.py as test
from test.py import *

print(test.k1)

set_v('k1',2)
set_v('k1',3)

print(test.k1)
输出:

1
after 2
after 3
3

Python中的全局变量仅在模块中是全局的

如果要修改导入模块中的全局变量,需要使用
module.variable
访问它

在测试的上下文中,这意味着:

import test.py as test
from test.py import *

print(test.k1)

set_v('k1',2)
set_v('k1',3)

print(test.k1)
输出:

1
after 2
after 3
3

FWIW,当Python使做某事变得非常困难时,这通常是一个信号,表明您不应该尝试去做它FWIW,当Python使做某事变得非常困难时,这通常是一个信号,表明您不应该尝试去做它我不确定——如果您使用“from xxx import*”,则应该将其读入全局名称空间。你说的是全局变量引用模块,这里只有一个模块。我不确定——如果你使用“from xxx import*”,它应该读入全局名称空间。你说的是全局变量引用模块,这里只有一个模块。这就是问题——为什么它们不同?导入带有“from xx import*”的内容时是否明确表示希望两者相同?否则,您将限定变量的范围,并且可以通过点符号访问它们。@schhibba,如我所说。它们属于不同的名称空间。通过导入,您不会合并名称空间。您只需将变量从外部名称空间导入到您的名称空间。@schhibba我应该提到的是,导入了一个副本。原始文件有自己的版本。这就是名称空间的概念,它是不相交的。解释器打印“k1”值,因为test.py被读入解释器名称空间。然而您要指出的是,它正在复制每个变量,这与代码的“全局”空间不同。如果我使用的是“fromtest import*”,test.k1构造不可用——这意味着解释器全局名称空间中的“k1”本身就是一个悬空引用。至少解释者的行为不一致。@schhibba一点也不。仅仅因为构造不可用并不意味着它当时不存在!这就是问题——为什么它们不同?导入带有“from xx import*”的内容时是否明确表示希望两者相同?否则,您将限定变量的范围,并且可以通过点符号访问它们。@schhibba,如我所说。它们属于不同的名称空间。通过导入,您不会合并名称空间。您只需将变量从外部名称空间导入到您的名称空间。@schhibba我应该提到的是,导入了一个副本。原始文件有自己的版本。这就是名称空间的概念,它是不相交的。解释器打印“k1”值,因为test.py被读入解释器名称空间。然而您要指出的是,它正在复制每个变量,这与代码的“全局”空间不同。如果我使用的是“fromtest import*”,test.k1构造不可用——这意味着解释器全局名称空间中的“k1”本身就是一个悬空引用。至少解释者的行为不一致。@schhibba一点也不。仅仅因为构造不可用并不意味着它当时不存在!