跨嵌套文件夹共享变量

时间:2019-11-15 03:28:26

标签: 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()opt之间共享实例化的main.py(又名change_config.py)。我尝试跟随但没有运气。问题是

  • 如果我在Config()中实例化了另一个change_config.py,则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

这也是可以预期的,因为opt中声明的main.pychange_config.py中的那个擦除了。但是预期的输出应该是

None 
10

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

2 个答案:

答案 0 :(得分:0)

让我们先来看一下Config.varConfig().var之间在python方面的区别。像Python中的其他所有内容一样,类是一个对象。类具有名称空间,因此Config.var是该名称空间中的变量。

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

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

因此,现在您可以使用几个选项。

  1. 第一个方法是完全不用实例化任何东西。您可以保留您的类变量config.Config.var,然后在类名称空间中进行更新。代码如下:

    main.py

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

    config.py

    class Config:
        var = None
    

    子文件夹/change_config.py

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

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

  2. 第二种方法是实例化Config,但是将引用放置在需要该引用的每个人都可以访问的地方。在这一点上,config.py实际上应该维护共享引用,因为那是存储实际配置的内容。我还建议完全删除类变量Config.var,以避免确切地引起您现在的困惑:

    main.py

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

    config.py

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

    子文件夹/change_config.py

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

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

答案 1 :(得分:-1)

您可以按如下所示更改应用程序,这将对您有所帮助

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

编辑

使用 singleton

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