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

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

# ../myproject/main.py

# Define global myList
global myList
myList = []

# Imports
import subfile

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

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

# ../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中,我有:

# ../myproject/subfile.py

# Import globfile
import globfile

# Save "hey" into myList
def stuff():
    globfile.myList.append("hey")

但是,还是没有成功。我应该如何实现这一点?我明白它不能这样工作,当两个文件不知道彼此(好子文件不知道主),但我不知道如何做到这一点,不使用io写入或pickle,这是我不想做的。


当前回答

问题是你从main.py定义了myList,但是subfile.py需要使用它。这里有一个干净的方法来解决这个问题:将所有全局变量移动到一个文件中,我称之为settings.py。这个文件负责定义全局变量并初始化它们:

# settings.py

def init():
    global myList
    myList = []

接下来,你的子文件可以导入全局变量:

# subfile.py

import settings

def stuff():
    settings.myList.append('hey')

注意,subfile不调用init() -该任务属于main.py:

# main.py

import settings
import subfile

settings.init()          # Call only once
subfile.stuff()         # Do stuff with global var
print settings.myList[0] # Check the result

通过这种方式,可以实现目标,同时避免多次初始化全局变量。

其他回答

我只是偶然看到这篇文章,并考虑发布我的解决方案,以防任何人遇到和我一样的情况,在开发的程序中有相当多的文件,而你没有时间考虑模块的整个导入序列(如果你从一开始就没有考虑到这一点,比如我)。

在这种情况下,在你初始化全局变量的脚本中,简单地编写一个类,如下所示:

class My_Globals:
  def __init__(self):
    self.global1 = "initial_value_1"
    self.global2 = "initial_value_2"
    ...

然后使用,而不是脚本中初始化全局变量的那行,而不是

global1 = "initial_value_1"

use

globals = My_Globals()

然后,我能够通过检索/更改这些全局变量的值

globals.desired_global

in any script, and these changes were automatically also applied to all the other scripts using them. All worked now, by using the exact same import statements which previously failed, due to the problems mentioned in this post / discussion here. I simply thought of global object's properties being changing dynamically without the need of considering / changing any import logic, in comparison to simple importing of global variables, and that definitely was the quickest and easiest (for later access) approach to solve this kind of problem for me.

当您从配置导入mySharedThing时,会出现命名空间噩梦。这一点再怎么强调也不为过。

使用from in other places也可以。

你甚至可以有一个完全空的配置模块。

# my_config.py
pass
# my_other_module.py
import my_config

def doSomething():
    print(my_config.mySharedThing.message)
# main.py
from dataclasses import dataclass
from my_other_module import doSomething
import my_config

@dataclass
class Thing:
    message: str

my_config.mySharedThing = Thing('Hey everybody!')
doSomething()

结果:

$ python3 main.py
Hey everybody!

但是使用你从那里拉来的物品会让你陷入沮丧。

# my_other_module.py
from my_config import mySharedThing

def doSomething():
    print(mySharedThing.message)

结果:

$ python3 main.py
ImportError: cannot import name 'mySharedThing' from 'my_config' (my_config.py)

也许你会尝试这样修正它:

# my_config.py
mySharedThing = None

结果:

$ python3 main.py
AttributeError: 'NoneType' object has no attribute 'message'

然后您可能会找到这个页面,并尝试通过添加init()方法来解决它。

但问题在于。

使用from your_file import *可以解决这个问题。它定义了所有内容,使其全局可用(当然,导入中的局部变量除外)。

例如:

##test.py:

from pytest import *

print hello_world

and:

##pytest.py

hello_world="hello world!"

问题是你从main.py定义了myList,但是subfile.py需要使用它。这里有一个干净的方法来解决这个问题:将所有全局变量移动到一个文件中,我称之为settings.py。这个文件负责定义全局变量并初始化它们:

# settings.py

def init():
    global myList
    myList = []

接下来,你的子文件可以导入全局变量:

# subfile.py

import settings

def stuff():
    settings.myList.append('hey')

注意,subfile不调用init() -该任务属于main.py:

# main.py

import settings
import subfile

settings.init()          # Call only once
subfile.stuff()         # Do stuff with global var
print settings.myList[0] # Check the result

通过这种方式,可以实现目标,同时避免多次初始化全局变量。

你可以把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])

And:

# ../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")