跨嵌套文件夹共享变量

2024-04-25 10:28:54 发布

您现在位置:Python中文网/ 问答频道 /正文

问题

许多人说他们的变量共享问题是用herehere提供的方法解决的,但是在我的用例中,这两种方法都不起作用,在我的用例中,所有配置都必须写在下面这样的类中。你知道吗

# config.py
class Config(object):
    var = None

我的项目结构看起来像

├── config.py
├── main.py
├── subfolder
|   ├── change_config.py

在这个项目中,main.py将调用change_config.py,它们都可以访问config.py中定义的变量。重要的是,change_config.py将修改变量(即,var),这些变量的值只有在运行时才知道。你知道吗

但是不清楚我应该如何共享实例化的Config()(aka。opt)穿过main.pychange_config.py。我试着跟着,但运气不好。问题是

  • 如果我在change_config.py中实例化另一个Config(),则main.py中的一个将被清除。你知道吗
  • 如果我不做第一个,那么名称opt将不会在change_config.py中解析
# main.py
import config
from subfolder import change_config

opt = config.Config()
print(opt.var)
change_config.change_config()
print(opt.var)
# change_config.py
import config

def change_config():
    opt.var = 10

更多信息

如果我运行main.py,那么

NameError: name 'opt' is not defined

这是预期的,因为opt从未在change_config.py中声明。你知道吗

如果我把change_config.py改成

# change_config.py
import config

opt = config.Config()
def change_config():
    opt.var = 10

我声明了另一个opt。没有错误,但已返回

None
None

这也是预期的,因为在main.py中声明的optchange_config.py中的声明擦除。但预期产出应该是

None 
10

所以问题是如何在main.py中与change_config.py共享opt


Tags: 项目方法pyimportnoneconfig声明here
2条回答

你可以改变你的申请如下,这将帮助你

config.py

x = 0

change_config.py

import config

def change_config():
    config.x = 10 #change the global config variable

main.py

import config
from subfolder import change_config

print(config.x)
change_config.change_config()
print(config.x)

运行main.py后,您将得到如下输出

0
10

编辑

使用单例

config.py

class Config(object):
    var = None
    def __new__(cls):
        if not hasattr(cls, 'instance'):
            cls.instance = super(Config, cls).__new__(cls)
        return cls.instance

main.py

from config import Config
from subfolder import change_config

opt = Config()
print('memory address :%s'%id(opt))
print(opt.var)
change_config.change_config()
print(opt.var)

change_config.py

from config import Config

opt = Config()
print('memory address :%s'%id(opt))
def change_config():
    opt.var = 10

您将得到如下输出

memory address :140185708587536
memory address :140185708587536
None
10

让我们先看看用python术语来说Config.varConfig().var之间的区别。像Python中的其他东西一样,类是一个对象。类有一个名称空间,因此Config.var是该名称空间中的一个变量。你知道吗

当您实例化Config时,比如用opt = Config(),opt现在是一个对象,也有一个名称空间。首先,当您请求值opt.var时,它返回Config.var,因为继承通常是如何工作的:如果一个对象没有属性,则先查看类,然后查看父类,等等。但是当您分配opt.var = 10时,您是在分配到实例的命名空间中。现在,当您请求opt.var的值时,它不再查看Config.var,因为opt有自己的var属性。你知道吗

现在请记住,main中的optchange_config中的opt是完全不同的实例,除了它们共享同一个类之外,它们不会相互影响。因此,当您设置change_config.opt.var = 10时,请求main.opt.var仍然返回None,因为实际的属性main.opt.var本身并不存在:它是从类命名空间返回Config.var。你知道吗

所以现在你有几个选择。你知道吗

  1. 第一个是根本不需要实例化任何东西。您可以保留类变量config.Config.var,只需在类名称空间中更新即可。代码如下所示:

    主.py

    from config import Config
    from subfolder.change_config import change_config
    
    print(Config.var)
    change_config()
    print(Config.var)
    

    配置.py

    class Config:
        var = None
    

    子文件夹/更改_配置.py

    from config import Config
    
    def change_config():
        Config.var = 10
    

    除了将导入更改为相对导入和从object中删除显式继承之外,您的代码只被修改为使用Config作为名称空间,而没有实例化它。

  2. 第二种方法是实例化Config,但是将引用放在每个需要它的人都可以访问的地方。此时,config.py应该真正维护共享引用,因为这是存储实际配置的内容。我还建议您完全删除类变量Config.var,以避免您现在遇到的混乱类型:

    主.py

    from config import opt
    from subfolder.change_config import change_config
    
    print(opt.var)
    change_config()
    print(opt.var)
    

    配置.py

    class Config:
        def __init__(self):
            self.var = None
    
    opt = Config()
    

    子文件夹/更改_配置.py

    from config import opt
    
    def change_config():
        opt.var = 10
    

    您可以通过在config.py的末尾添加del Config,使您的配置成为Config的一个更深入的实例。这将使创建另一个类的冲突实例变得更加困难,因为它不容易通过模块获得。对Config的唯一引用将通过opt的继承层次结构。

相关问题 更多 >