首页 > 解决方案 > 动态创建可以从任何地方导入的不可变常量?

问题描述

在我的python 包中,我有一个entry_point run.py 文件,它将种子(例如42)和cuda 设备(例如“cuda:0”)作为命令行参数。

由于这两个变量在整个包的不同位置使用,我不想将它们作为参数从函数传递到函数。因此,我做了以下事情:

实用程序.py:

import random

import numpy as np
import torch


def set_device(device: str):
    global _DEVICE
    _DEVICE = torch.device(device)


def get_device() -> torch.device:
    return _DEVICE


def set_seed_number(seed: int):
    global _SEED
    _SEED = seed


def set_seeds():
    torch.manual_seed(_SEED)
    random.seed(_SEED)
    np.random.seed(_SEED)

然后在 run.py 我通过调用设置这些变量一次:

from package.utils import set_device, set_seed_number

...

set_device(device)
set_seed_number(seed=seed)

现在我可以从包中的任何位置导入和调用get_device()andset_seeds方法,而不必将这些变量作为参数传递。

到目前为止,这种方法效果很好,但是在阅读了强烈建议不要在 python 中使用 globals 之后,我想知道是否有更 Pythonic 的方式来实现上述目标?

我已经考虑过有一个专用的 Singleton 类,它会动态地实例化这些常量,但我不确定它是否以及如何工作,以及它是否会被认为更“pythonic”。

已经感谢您的回答,也许您可​​以指出一些似乎适用于这种情况的模式。我只能猜测我不是第一个试图实现上述目标的人。

标签: pythondynamicsingletonglobal

解决方案


global老实说,如果它被谨慎使用并且只有当有充分的理由这样做时,我看不出有什么问题。(我认为强烈的挫败感global是因为它经常被滥用。)

但是对于您提出的自定义类,无需实例化它——您只需设置类变量即可。

main.py

import settings

settings.set_foo(3)
print(settings.Settings.foo)

settings.py

class Settings:
    pass

def set_foo(x):
    Settings.foo = x

这在原则上与将数据项放入其他一些可变集合(例如字典)然后将它们设置在定义它的模块(或导入它的另一个模块)中的函数中没有什么不同。

main.py

import settings

settings.set_foo(3)
print(settings.settings['foo'])

settings.py

settings = {}

def set_foo(x):
    settings['foo'] = x

推荐阅读