Python - 从其他模块中的函数重新分配全局变量的最佳方法

标签 python import module global-variables

我有一个模块,我称之为entities.py - 其中有2个类和2个全局变量,如下图所示:

FIRST_VAR = ...
SECOND_VAR = ...

class FirstClass:
    [...]

class SecondClass:
    [...]
我还有另一个模块(我们暂时称它为 main.py),我在其中导入类和常量,如下所示:
from entities import FirstClass, SecondClass, FIRST_VAR, SECOND_VAR
在同一个“main.py”模块中,我有另一个常量:THIRD_VAR = ...和另一个类,其中使用了所有导入的名称。
现在,我有一个函数,只有在满足某个条件时才会调用它(在我的例子中,将配置文件路径作为 CLI 参数传递)。作为我最好的选择,我将其编写如下:
def update_consts_from_config(config: ConfigParser):
    global FIRST_VAR
    global SECOND_VAR
    global THIRD_VAR
    FIRST_VAR = ...
    SECOND_VAR = ...
    THIRD_VAR = ...
这工作得很好,尽管 PyCharm 指出了两个问题,至少我不认为这是准确的。from entities import FirstClass, SecondClass, FIRST_VAR, SECOND_VAR - 这里它警告我 FIRST_VAR 和 SECOND_VAR 是未使用的导入,但根据我的理解和测试,它们被使用并且不会在其他地方重新声明,除非函数 update_consts_from_config被调用。
此外,在 update_consts_from_config 下功能:global FIRST_VAR - 在这一行和下一行,它说
全局变量 FIRST_VAR 在模块级别未定义
我的问题是,我是否应该真正关心这些警告和(因为我认为代码是正确且清晰的),还是我错过了一些重要的东西,应该在这里提出一些不同的东西?
我知道我可以做一些事情:
import entities
from entities import FirstClass, SecondClass

FIRST_VAR = entities.FIRST_VAR
SECOND_VAR = entities.SECOND_VAR
从那里开始工作,但这对我来说似乎有点过头了,entities模块只有我必须在 main.py 中导入的内容这也严格依赖于它,因此我宁愿坚持明确导入这些名称,也不愿通过 entities. 引用它们。正因为如此
您认为这里的最佳做法是什么?我希望我的代码清晰、明确并且以某种方式优化。

最佳答案

仅导入实体,然后在其 namespace 中引用变量访问/修改它们。
注意:这种模式,修改其他模块中的常量(对于纯粹主义者来说,与其说是全局常量,不如说是全局常量)是合理的。我有很多使用常量而不是 magic variables 的情况,作为模块级配置。但是,例如为了测试,我可能会进入并修改这些常量。假设将缓存到期时间从 2 天切换到 0.1 秒以测试缓存。或者像你建议的那样,覆盖配置。小心行事,但它可能很有用。
主文件 :

import entities

def update_consts_from_config(FIRST_VAR):
    entities.FIRST_VAR = FIRST_VAR

firstclass = entities.FirstClass()

print(f"{entities.FIRST_VAR=} before override")
firstclass.debug()
entities.debug()

update_consts_from_config("override")

print(f"{entities.FIRST_VAR=} after override")
firstclass.debug()
entities.debug()
实体.py :
FIRST_VAR = "ori"

class FirstClass:
    def debug(self):
        print(f"entities.py:{FIRST_VAR=}")


def debug():
    print(f"making sure no closure/locality effects after object instantation {FIRST_VAR=}")
$ python main.py

entities.FIRST_VAR='ori' before override
entities.py:FIRST_VAR='ori'
making sure no closure/locality effects after object instantation FIRST_VAR='ori'
entities.FIRST_VAR='override' after override
entities.py:FIRST_VAR='override'
making sure no closure/locality effects after object instantation FIRST_VAR='override'
现在,如果 FIRST_VAR 不是字符串、int 或其他类型的不可变类型,我认为您应该能够单独导入它并对其进行变异。点赞SECOND_VAR.append("config override")在 main.py 中。但是在 main.py 中赋值给全局只会影响 main.py 绑定(bind),所以如果你想在 main.py 和实体和其他模块之间共享实际状态,每个人,不仅仅是 main.py 需要 import entities然后访问 entities.FIRST_VAR .
哦,如果你有:
class SecondClass:

   def __init__(self):
      self.FIRST_VAR = FIRST_VAR
那么它的不可变字符串/整数的实例级值将不是 受到任何覆盖的影响 之后 实例创建。列表或字典等可变变量 受到影响,因为它们都是指向同一个变量的不同绑定(bind)。
最后,对于那些“棘手”的命名空间。 global在您的原始代码中的意思是:“不要将 FIRST_VAR 视为要在 update_consts_from_config 的本地命名空间中分配的变量,而是将其分配给 main.py 全局的脚本级命名空间”。
它确实 不是 意思是“将它分配给 entities.py main.py 之间神奇地共享的某个全局状态”。 __builtins__可能是那个野兽,但修改它在 Python 中被认为是非常糟糕的形式。

关于Python - 从其他模块中的函数重新分配全局变量的最佳方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64834953/

相关文章:

python - 如何为通用工厂方法创建类型提示?

Python - 如何检查 JSON 中的键是否为空值?

python 包装器函数在装饰器中接受参数

mysql - 什么是 TYPO3 引用索引?为什么它会包含过时的值?

apache-flex - 使用多个模块时优化 Flex

python - 如何使用python复制和粘贴现有工作簿中的现有工作表?

python - 使用 "."的相对导入在 python 中总是有意义吗?

python - Boost.Python 示例,Windows 7 x64, "ImportError: DLL load failed: The specified module could not be found."

mysql - 如何导入 .sql 文件

module - 具有已实现 ocaml 功能的类型模块