从另一个模块修改一个模块的属性是一种不好的做法吗?

我想定义一堆可以导入到我的项目中的所有模块中的配置变量。这些变量的值在运行时是恒定的,但在运行前是未知的;它们取决于输入。通常我会在顶部模块中定义一个字典,它将传递给其他模块中的所有函数和类;但是,我认为简单地创建一个空白的config.py模块可能会更干净,该模块将由顶部模块动态填充配置变量:


# top.py

import config

config.x = x


# config.py

x = None


# other.py

import config

print(config.x)

我喜欢这种方法,因为我不必将参数保存为其他模块中类的属性;这对我来说很有意义,因为参数并不描述类本身。


这可行,但是这被认为是不好的做法吗?


蝴蝶不菲
浏览 130回答 2
2回答

元芳怎么了

这样的问题可能存在争议。但我通常会说是的,这是“不好的做法”,因为变革的范围和影响确实变得模糊。请注意,您描述的用例实际上不是关于共享配置,而是关于程序函数、对象、模块交换数据的不同部分,因此它是(元)变量的一些变体global。读取通用配置值可能没问题,但一路更改它们...您可能会忘记在导入模块/修改值时发生的情况以及顺序。例如假设config.py和 两个模块m1.py:import configprint(config.x)config.x=1和m2.py:import configprint(config.x)config.x=2和 amain.py就这样做:import m1import m2import configprint(config.x)或者:import m2import m1import configprint(config.x)您在每个模块以及其他任何模块(包括main.py此处)中找到配置的状态取决于导入发生的顺序以及谁在何时分配什么值。即使对于完全在您控制之下的程序,这也可能很快变得令人困惑(以及错误的根源)。对于运行时数据以及在对象和模块之间传递信息(您的示例确实是这样,而不是在模块之间预定义和共享的配置),我建议您考虑在自定义状态(配置)对象中描述信息并将其传递通过适当的接口。但实际上可能只需要一个函数/方法参数即可。确切的形式取决于您到底想要实现什么以及您的整体设计是什么。在您的示例中,other.py之前调用或导入时的行为有所不同top.py,在最小的示例中可能仍然看起来很明显且易于管理,但实际上并不是一个非常合理的设计。任何阅读代码的人(包括未来的你)都应该能够遵循其逻辑,而这个 IMO 打破了它的流程。对于您所描述的内容,最简单(也是程序性的)示例,现在我希望能够更好地理解,那就是重新other.py创建您当前的行为:def do_stuff(value):    print(value)  # We did something useful hereif __name__ == "__main__":   do_stuff(None)  # Could also use config with defaults您top.py可能是入口点并协调导入和执行:import otherx = get_the_value()other.do_stuff(x)您当然可以引入一个接口来配置do_stuff一个dict或一个自定义类,即使使用默认实现config.py:class Params:    def __init__(self, x=None):        self.x = x和你的other.py:def do_stuff(params=config.Params()):    print(params.x)  # We did something useful here在你的上top.py你可以使用:params = config.Params(get_the_value())other.do_stuff(params)但您也可以拥有任何特定于用例的值源:class TopParams:    def __init__(self, url):        self.x = get_value_from_url(url)params = TopParams("https://example.com/value-source")other.do_stuff(params)x甚至可以是property您每次访问它时检索的内容...或者在需要时懒惰地检索然后缓存...同样,这实际上是您需要做什么的问题。

30秒到达战场

“从一个模块修改另一个模块的属性是一种不好的做法吗?”这被认为是不好的做法——违反了德米特法则,这实际上意味着“与朋友交谈,而不是与陌生人交谈”。对象应该公开行为和功能,但应该隐藏数据。DataStructures 应该公开数据,但不应该有任何方法(公开的)。德米特定律不适用于此类数据结构。OOP 纯粹主义者可能会使用 setter 和 getter 来覆盖此类 DataStructures,但它实际上在 Python 中没有增加任何价值。我保留配置的首选方法是(此处不使用 attrs):# conf_xy.py"""config is code - so why use damned parsers, textfiles, xml, yaml, toml and all thatif You just can use testable code as config that can deliver the correct types, etc.as well as hinting in Your favorite IDE ?Here, for demonstration without using attrs package - usually I use attrs (read the docs)"""class ConfXY(object):        def __init__(self) -> None:        self.x: int = 1        self.z: float = get_z_from_input()        ...conf_xy=ConfXY()# other.pyfrom conf_xy import conf_xy...y = conf_xy.x * 2... 
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python