我对全局变量的工作方式感到困惑。我有一个大项目,大约有50个文件,我需要为所有这些文件定义全局变量。

我所做的就是在我的项目main.py文件中定义它们,如下所示:

# ../myproject/main.py

# Define global myList
global myList
myList = []

# Imports
import subfile

# Do something
subfile.stuff()
print(myList[0])


我正尝试在myList中使用subfile.py,如下所示

# ../myproject/subfile.py

# Save "hey" into myList
def stuff():
    globals()["myList"].append("hey")


我尝试了另一种方法,但是也不起作用

# ../myproject/main.py

# Import globfile    
import globfile

# Save myList into globfile
globfile.myList = []

# Import subfile
import subfile

# Do something
subfile.stuff()
print(globfile.myList[0])


subfile.py里面我有这个:不行我应该如何实施呢?我知道当两个文件彼此之间并不真正了解时(子文件不知道主文件),它就不能那样工作,但是我不知道如何在不使用io编写或pickle的情况下做到这一点。我不想做。

评论

实际上,您的第二种方法对我来说很好。 main.py正确打印出“嘿”。通过“没用”,您可以更具体地说明我的意思吗?

@rodion:导入循环-子文件中的代码尝试导入globfile,该文件在主体中又将自身导入回来
NameError:未从main.py行print(globfile.myList [0])
定义名称'myList'
我的理解是__init__.py也可以用于定义全局变量,这种用法是否过时?应该优先使用config.py文件方法吗?

#1 楼

问题是您从myList定义了main.py,但是subfile.py需要使用它。这是解决此问题的一种干净方法:将所有全局变量移至一个文件,我将此文件称为settings.py。该文件负责定义全局变量并对其进行初始化:

# settings.py

def init():
    global myList
    myList = []

接下来,您的subfile可以导入全局变量: br />请注意,subfile不会调用init() -该任务属于main.py

评论


我喜欢通用方法,但不喜欢整个init()东西。仅在首次导入模块时对它们进行评估,因此完全可以在模块主体中初始化这些变量。

–Kirk Strauser
2012年10月23日在17:10

+1柯克:我同意。但是,我的方法避免了其他模块在主程序启动之前修改globals.myList的情况。

– Hai Vu
2012年10月23日在20:52

您应该将其称为全局名称以外的其他名称,这是一个内置名称。 PyLint发出警告:“重新定义内置的'globals'(redefined-builtin)“

–特斯布里利格
15年1月27日在20:29



谢谢。知道如何通过使用此文件结构来消除Eclipse PyDev中出现的“从导入中删除未定义变量”错误(即,从settings.py导入全局变量)吗?我不得不禁用PyDev中的错误,这并不理想。

–弗朗克·德农库尔
2015年8月20日在7:08



@FranckDernoncourt对不起,我没有使用Eclipse,所以我比你更笨。

– Hai Vu
15年8月20日在12:10

#2 楼

请参阅关于在模块之间共享全局变量的Python文档: />
config.py:


x = 0   # Default value of the 'x' configuration setting


将config模块导入到应用程序的所有模块中;然后该模块就可以用作全局名称。

main.py:


import config
print (config.x)





from config import x
print (x)





通常,请勿使用从模块名import *。这样做会使导入者的名称空间变得混乱,并使短绒更难检测未定义的名称。


评论


救生员-仅用于该链接!

–卡通军长
18年8月8日在4:42

这似乎比接受的答案更干净。

–JoeyC
19年1月23日,0:48

请注意,您不能使用from config import x来设置x,而只能使用import config

– Yariv
19年11月20日在7:21

最简单的解决方案!谢谢

–user1297406
2月11日在16:35

好答案。干净,酥脆和惯用语。

–印地语
10月11日18:36

#3 楼

您可以将Python全局变量视为“模块”变量-因此,它们比C语言中的传统“全局变量”有用。

全局变量实际上是在模块的__dict__和可以从该模块外部作为模块属性进行访问。

因此,在您的示例中:

# ../myproject/main.py

# Define global myList
# global myList  - there is no "global" declaration at module level. Just inside
# function and methods
myList = []

# Imports
import subfile

# Do something
subfile.stuff()
print(myList[0])


和:

# ../myproject/subfile.py

# Save "hey" into myList
def stuff():
     # You have to make the module main available for the 
     # code here.
     # Placing the import inside the function body will
     # usually avoid import cycles - 
     # unless you happen to call this function from 
     # either main or subfile's body (i.e. not from inside a function or method)
     import main
     main.mylist.append("hey")


评论


哇,通常人们希望两个互相导入的文件陷入无限循环。

– Nikhil VJ
18年8月24日在4:11



ha乍看起来是这样,不是吗? def stuff()中发生的情况是,导入不会在文件加载时运行。.仅在调用stuff()函数时运行。因此,从main开始,我们导入子文件,然后调用subfile.stuff(),然后再导入main ... no循环,只需在main中导入一次。请参阅subfile.py示例中有关导入周期的注释。

–约翰
19年4月18日在18:59



#4 楼

使用from your_file import *应该可以解决您的问题。它定义了所有内容,以便可以全局使用(当然,当然也包括导入中的局部变量)。

例如: >和:

##test.py:

from pytest import *

print hello_world


评论


除非您分配给一个这样的变量

–jsbueno
2012年10月23日16:03
我个人不惜一切代价避免使用import *,以便引用是显式的(并且不会造成混淆)。此外,您何时曾在任何模块中实际使用过所有“ *”引用?

–雷神召唤师
2014-09-18 20:30



请勿导入*。您的全局变量将不再保持同步。每个模块都有自己的副本。在一个文件中更改变量不会在另一个文件中反映出来。 docs.python.org/2/faq/…中也警告它。

–伊莎·哈森(Isa Hassen)
16-2-7在14:11

#5 楼

Hai Vu的答案很好用,只需发表一条评论:

如果您在其他模块中使用全局变量,并且想要动态设置全局变量,请注意在设置全局变量之后导入其他模块,例如:

# settings.py
def init(arg):
    global myList
    myList = []
    mylist.append(arg)


# subfile.py
import settings

def print():
    settings.myList[0]


# main.py
import settings
settings.init("1st")     # global init before used in other imported modules
                         # Or else they will be undefined

import subfile    
subfile.print()          # global usage


#6 楼

您的第二次尝试将非常有效,实际上是处理要全局使用的变量名的好方法。但是您在最后一行有名称错误。它应该是这样的:

# ../myproject/main.py

# Import globfile    
import globfile

# Save myList into globfile
globfile.myList = []

# Import subfile
import subfile

# Do something
subfile.stuff()
print(globfile.myList[0])


查看最后一行? myList是globfile(而不是子文件)的attr。这将随您想要。

迈克

#7 楼

我只是碰到了这篇文章,并想到要发布我的解决方案,以防万一有人和我处于相同的情况,开发的程序中有很多文件,而您却没有时间思考整个问题。模块的导入顺序(如果您从一开始就没想到正确的顺序,例如我那样)。
在这种情况下,在初始化全局变量的脚本中,只需编写一个类表示为:
class My_Globals:
  def __init__(self):
    self.global1 = "initial_value_1"
    self.global2 = "initial_value_2"
    ...

,然后使用而不是初始化全局变量的脚本行代替
global1 = "initial_value_1"

使用
globals = My_Globals()

然后,我可以通过任何脚本中的
globals.desired_global

检索/更改任何这些全局变量的值,并且使用这些更改,这些更改也自动应用于所有其他脚本。由于之前在此帖子/讨论中提到的问题,所有操作现在都可以使用完全相同的import语句(以前失败)进行。与简单地导入全局变量相比,我只是认为全局对象的属性是动态变化的,而不需要考虑/更改任何导入逻辑,这无疑是解决此类问题的最快,最简单的方法(供以后访问)对我来说。