【问题标题】:How to use a 'global' variable in python?如何在 python 中使用“全局”变量?
【发布时间】:2015-08-19 13:08:57
【问题描述】:

在我的问题中,我有一个用户正在启动的 python 代码,例如:

# file main.py
import sys
import mymodule
config = sys.argv[1]

它导入另一个包含函数、类等的模块,例如

# module.py
def check_config():
    # do something with the content of 'config'
class Module(object):
    # does something with the content of 'config'

如何从module.py 中访问“config”的值?我应该在这里使用“全局”变量吗?还是有更复杂的 Pythonic 方法来解决这个问题?

另外,我不想为我在其他模块中使用的每个函数和类定义一个参数“config”...

进一步说明:main.py 导入其他模块,而不是相反...

【问题讨论】:

    标签: python global-variables


    【解决方案1】:

    您应该将config 作为参数传递,而不是试图让global 执行此操作。

    文件 main.py

    import sys
    import mymodule
    config = sys.argv[1]
    
    checked = mymodule.check_config(config)
    mod = mymodule.Module(config)
    

    模块.py

    def check_config(config):
        # do something with the content of 'config'
    class Module(object):
        # does something with the content of 'config'
        def __init__(self, config):
            # initialise with config
    

    尽可能避免使用global。如果您需要修改config,只需一个模块函数返回即可。

    config = change_config(config)
    

    模块.py

    def change_config(config):
        ...
        return config
    

    但是,另一种方法是在module.py 中定义一个值,它将存储默认情况下不包含任何内容的此信息。然后当file main.py 导入module.py 并且配置数据准备好后,您可以将数据分配给module.py 的配置名称。像这样:

    文件 main.py

    import sys
    import mymodule
    config = sys.argv[1]
    
    mymodule.config = config
    
    mymodule.test_config()
    mymodule.check_config()
    mymodule.Module()
    

    模块.py

    config = None
    
    def test_config():
        print config 
        # this will refer to the value supplied from file main.py
    

    但是请注意,模块和主文件中的值不会被连接。如果您出于任何原因重新分配 file main.py 中的配置,则必须再次将该值传递给模块。但是,如果您传递一个可变值(如 dict 或列表),那么您可以在 file main.py 中对其进行修改,并且这些值将被共享。

    【讨论】:

    • Bus 正如我所提到的,我可能有几十个类和数百个函数。你的方法似乎不是很“pythonic”。
    • @Alex 传递参数是一种让函数获取该参数的干净方法。使用global 会不清楚,因为它不太明确。明确 Pythonic。
    • 您如何看待此处描述的方法:effbot.org/pyfaq/…
    • 这在一定程度上可行,但导入很棘手,我认为talk about it on chat 对我们来说更容易,因为我可能误解了你打算如何使用它。
    • @Alex 编写“Pythonic”代码并不是要减少输入——而是要明确和清晰。如果您的每个函数都需要config,那么最明确的做法是将配置作为输入参数。您可能考虑将配置包装到一个类中,并使所有需要它的函数成为该类的方法,但这可能不是必需的。
    【解决方案2】:

    我不建议使用全局变量,但如果你这样做,这是你应该使用的设计。 config需要在mymodule中定义;导入模块后,您可以按照当前设置config 的方式设置mymodule.config 的值。

    # file main.py
    import sys
    import mymodule
    mymodule.config = sys.argv[1]
    
    
    # module.py
    # The exact value doesn't matter, as long as we create the name.
    # None is good as it conveys the lack of a value; it's part of your
    # module's contract, presumably, that a proper value must be assigned
    # before you can use the rest of the module.
    config = None
    def check_config():
        # do something with the content of 'config'
    class Module(object):
        # does something with the content of 'config'
    

    【讨论】:

    • 我想这是与此处给出的类似方法:effbot.org/pyfaq/…?
    • 是的,这不是一个很难重新创建的模式。本质上,该模块被视为只实例化一次的类。模块全局变量是实例变量,任何模块函数都是方法。
    【解决方案3】:

    全局变量几乎永远不是答案。只允许“库”(module.pymymodule.py,您似乎同时使用)中的函数和类接受参数。所以:

    mymodule.py

    def check_config(configuration):
        pass
    
    class Module(object):
        def __init__(self, configuration):
            self.config = configuration
    
    class ConfigError(Exception):
        pass
    

    那么当你想在你的“应用”代码中使用它们时:

    ma​​in.py

    import sys
    import mymodule
    
    config = sys.argv[1]
    
    if mymodule.check_config(config):
        myobject = mymodule.Module(config)
    else:
        raise mymodule.ConfigError('Unrecognized configuration format.')
    

    【讨论】:

    • 与以下评论相同:这可能有效,但随后Module 正在调用不同的函数和类,而这些函数和类又会调用其他函数和类。对于他们中的每一个,我必须定义相同的论点。我觉得不好看...
    • 嗯,代码重用是一回事。没有真正遵循你的逻辑。另一种方法是将所有配置代码放入 config.py 文件中,例如,然后将 import config 放入所有库文件中,但您提到您不想在库中使用 import。您过度限制了可接受的解决方案集。
    【解决方案4】:

    您能描述一下您的应用应该做什么吗?因为现在还不清楚,为什么你想要它。 也许环境变量可以帮助你?

    顺便说一句,您可以在一个地方(模块)读取配置文件,并从中导入您需要的所有内容。

    config.py

       import os
       if os.environ['sys'] == 'load_1':
            import load_1 as load
            i = 12
       else:
            import load_2 as load
            i = 13
    

    ma​​in.py

       import config
    
       config.load("some_data")
       print config.i
    

    【讨论】:

    • 但是,在相同python代码的不同实例之间,模块和函数中使用的变量可能不同。我开始例如5 个实例并行运行,但具有不同的“配置”或其他。因此,您的方法无法解决我的问题。
    • 这真是莫名其妙!更有理由接受每次将配置显式传递给对象的概念,接受我的解决方案或@SuperBiasedMan 的。
    • @Alex,你应该用不同的配置运行它。您可以将类似环境变量的配置传递给config 模块,解析此配置并在您想要的每个模块中使用它。
    猜你喜欢
    • 1970-01-01
    • 2012-01-31
    • 1970-01-01
    • 1970-01-01
    • 2013-06-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-14
    相关资源
    最近更新 更多