我对全局变量的工作原理有点困惑。我有一个大项目,大约有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,这是我不想做的。


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

例如:

##test.py:

from pytest import *

print hello_world

and:

##pytest.py

hello_world="hello world!"

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

您的第二次尝试将会完美地工作,这实际上是一种处理您希望全局可用的变量名的好方法。但是你在最后一行有一个名字错误。应该是这样的:

# ../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,不是subfile。这将如你所愿。

Mike


问题是你从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

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


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

请参阅Python关于跨模块共享全局变量的文档:

在单个程序中跨模块共享信息的规范方法是创建一个特殊的模块(通常称为config或cfg)。 config.py: x = 0 # 'x'配置设置的默认值 在应用程序的所有模块中导入配置模块;然后,模块就可以作为全局名称使用。 main.py: 导入配置 打印(config.x)


一般情况下,不要使用from modulename import *。这样做会使导入器的名称空间变得混乱,并使linter更难检测到未定义的名称。


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

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

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.


基于上面的答案和链接,我创建了一个名为global_variables.py的新模块:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

# ==============================================================================
#
#       global_variables.py - Global variables shared by all modules.
#
# ==============================================================================

USER = None                 # User ID, Name, GUID varies by platform

def init():
    """ This should only be called once by the main module
        Child modules will inherit values. For example if they contain
        
            import global_variables as g
            
        Later on they can reference 'g.USER' to get the user ID.
    """
    global USER

    import getpass
    USER = getpass.getuser()

# End of global_variables.py

然后在我的主模块中,我使用这个:

import global_variables as g
g.init()

在另一个子导入模块,我可以使用:

import global_variables as g
# hundreds of lines later....
print(g.USER)

我只花了几分钟在两个不同的python多模块程序中测试,但到目前为止,它工作得很完美。


当您从配置导入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()方法来解决它。

但问题在于。