简体   繁体   English

在Python中访问全局变量时的导入行为

[英]import behavior when accessing global variables in Python

In bar.py : bar.py中

var = 1
def set_var():
    global var
    var = 2

In foo.py : foo.py中

from bar import *

print(var)
set_var()
print(var)

In foo2.py : foo2.py中

import bar

print(bar.var)
bar.set_var()
print(bar.var)

If I run foo.py the output is: 如果我运行foo.py,则输出为:

1
1

but if I run foo2.py the output is: 但如果我运行foo2.py输出是:

1
2

which is what I would expect. 这是我所期待的。

I only would like to understand this behavior, since I am new to Python and haven't find a good reason for this. 我只想了解这种行为,因为我是Python的新手并没有找到合理的理由。

PD: Additional info. PD:其他信息。 I want to develop a module that uses a singleton object and I have some legacy code that uses this object. 我想开发一个使用单例对象的模块,并且我有一些使用该对象的遗留代码。 I would prefer not to prefix every reference to that object in the legacy code, so that is why I though that importing the module with the from library import object syntax would help. 我宁愿不在遗留代码中为该对象的每个引用添加前缀,这就是为什么我使用from库导入对象语法导入模块会有所帮助。

So in the library I have functions that access the global object to configure it just as in the example (bar.py). 所以在库中我有一些函数可以访问全局对象来配置它,就像在示例中一样(bar.py)。 And in the legacy code I hoped it only would be needed to do some kind of import as it is done in foo.py. 在遗留代码中,我希望只需要进行某种导入,就像在foo.py中一样。

Thanks for the guidance. 感谢您的指导。

EDITED: SECOND EXAMPLE 编辑:第二个例子

In bar.py 在bar.py

var_list = list(range(0, 2))
var_list2 = list(range(0, 2))

def set_var():
    global var_list
    var_list = list(range(0, 3))
    var_list2.append(2)

In foo.py 在foo.py中

from bar import *

print(var_list)
print(var_list2)
set_var()
print(var_list)
print(var_list2) 

The output is: 输出是:

[0, 1]
[0, 1]
[0, 1]
[0, 1, 2]

I understand that in set_var we are creating a new object with list() , but I would expect in foo.py to access this new object when I refer to it with var_list (just as it would work using the syntax bar.var_list ). 我理解在set_var中我们正在用list()创建一个新对象,但是当我用var_list引用它时,我希望在foo.py中访问这个新对象(就像使用语法bar.var_list一样 )。 I need some more background. 我需要更多背景知识。

Thanks 谢谢

"var" in bar.py is bar.var . bar.py中的“var”是bar.var Always (unless it's __main__.var , but that's a different issue). 总是(除非是__main__.var ,但这是一个不同的问题)。 Any manipulation of that name happens only in/to that module and not to copies that were made any where else such as those done via from bar import ... . 对该名称的任何操作只发生在该模块中,而不是发生在其他任何地方的副本,例如通过from bar import ...完成的那些from bar import ...

There are two components to this behavior: 此行为有两个组件:

  1. As @Ignacio already explained, so-called "globals" in python actually have module-wide scope. 正如@Ignacio已经解释的那样,python中所谓的“全局”实际上具有模块范围。

  2. A variable name in python points to an object (mutable or immutable, class or integer, it's all the same). python中的变量名指向一个对象(可变或不可变,类或整数,它们都是相同的)。 When you assign to an existing name, you break its association with whatever it was pointing to before. 分配给现有名称时,将断开与之前指向的任何名称的关联。

So this is what foo does: 所以这就是foo所做的:

# import
foo.var = bar.var
foo.set_var = bar.set_var

print(foo.var)
foo.set_var()   # sets bar.var
print(foo.var)

foo2 , of course, sets and prints bar.var . 当然, foo2设置并打印bar.var

Regarding your second example: You can modify a list without breaking its associations with the variables that point to it. 关于你的第二个例子:你可以修改一个列表而不破坏它与指向它的变量的关联。 So the changes to var_list2 are visible everywhere (note that you never assign to it). 因此var_list2的更改随处可见(请注意,您永远不会分配给它)。 But since you assign to var_list , it behaves like var in the first example. 但是,因为您分配给var_list ,它在第一个示例中的行为类似于var

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM