mha*_*vel 5 python module initialization package
我已经阅读了有关__init__.py
文件的文档以及关于SO的一些不错的问题,但是我仍然对其正确用法感到困惑。
我有一个包含许多程序包和子程序包的代码。我定义了许多类,其中一些我需要为整个用户会话创建一个(只有一个)实例。这些新对象然后在代码的不同部分中使用,因此,只要我(或用户)更新该对象中的数据/信息,便会在所有代码中使用它,而无需进行任何其他更改。更清楚地说,让我向您展示我所谈论的基本方案。
该代码的结构过于简化:
root/
__init__.py
tools/
__init__.py
... (some modules)
aliases.py (which defines the class Aliases)
physics/
__init__.py
... (some modules)
constants/
... (some modules)
constants.py (which defines the class Ctes)
units.py (which defines the class Units)
Run Code Online (Sandbox Code Playgroud)
在代码中,我需要管理别名,单位和常量。我发现处理该问题的方法是为每个实例创建一个实例,并在所有代码中使用它。例如,通过这种方法,我可以确定,如果在代码仍在运行时添加了别名,则可以在代码的任何位置使用它,因为只有一个共享的别名实例。这就是我所需要的(顺便说一句,单位和常量也是如此)。
就目前而言,我认为这不是最好的方法。确实,我在声明该类之后,在同一个文件中直接创建了别名的实例,例如别名:
在 root/tools/aliases.py
import ... (stuff
class Aliases(object):
"""The Aliases manager"""
...
ALIASES = Aliases()
Run Code Online (Sandbox Code Playgroud)
然后,在需要使用Aliase的任何文件中,我都执行以下操作:
在any_file.py
(代码中的任何位置)
from root.tools.aliases import ALIASES
ALIASES.method1() # possibly in functions or other classes
ALIASES.method2() # ... etc
Run Code Online (Sandbox Code Playgroud)
对于其他一些类,我什__init__.py
至在代码的根目录下使用该文件:
在 root/__init__.py
# CTES is the instance of Ctes() created in root/physics/constants/constants.py
from root.physics.constants.constants import CTES
CTES.add(...) # add a new constant that needs to be known
Run Code Online (Sandbox Code Playgroud)
(当然,CTES不仅存储一些常量,我定义了一些利用它们的方法,因此将它们包含在此类中而不是仅将它们定义为模块中的常规python常量是有意义的)
我想知道我是否做对了(可能不是)。也许最好使用文件__init__.py
并在其中启动共享实例。但这是否会带来一些问题(例如依赖周期或增加的内存使用量……)?另外,如何在代码的其他地方使用创建的实例?像这样?:
在 root/tools/__init__.py
import root.tools.aliases as Al
ALIASES = Al.Aliases()
# should I delete the imported module: del Al ??
Run Code Online (Sandbox Code Playgroud)
然后在 any_file.py
from root.tools import ALIASES
ALIASES.method(...)
Run Code Online (Sandbox Code Playgroud)
还是应该将所有这些实例更好地包含在root/shared.py
我导入的文件(例如)中,以root/__init__.py
确保它已启动?
我已经读过很多次了,最好将__init__.py
文件保持为空(这在我的代码中现在是这种情况,当然对于除外root/__init__.py
)。你怎么看?
我有点迷茫(从我不太清楚的事实中,您可能会看到这一点)。任何帮助/建议都非常受欢迎。我想避免使用任何非pythonic解决方案,或者可能会使用户感到困惑或使事情变得不安全的解决方案。
您在模块中内联创建单个实例时所做的事情是很好的。使用全局变量没有任何问题(除非它们不合适,但这适用于任何语言功能)。唯一的潜在缺点是,如果您导入该模块而不使用它,则会浪费资源来初始化该类。除非你的类在创建时正在做一些非常繁重的事情(我非常怀疑),否则这种影响可以忽略不计。我唯一建议的是你调整你的命名。您的类可能应该以下划线开头,以便模块的用户知道不要触摸它,并且您的实例应该是小写的。您使用的方法不会造成任何不良副作用。
没有人说你必须将所有类放在自己的文件中,或者你必须使用类。也许带有函数的别名模块和模块全局变量中的“私有”状态对您来说更有意义。由于您没有使用对象系统来获取具有独立状态的多个实例,因此创建类的唯一原因是您更喜欢以这种方式组织代码和 API。这里最重要的是您对代码的组织方式以及模块的使用方式感到满意。在我看来,过多使用面向对象技术比使用过少更有可能让用户感到困惑。只要确保在您确实需要课程时就开设课程即可。
还有很多其他的单例方法。这是我第一次听说“博格模式”,对我来说这听起来既浪费又愚蠢,但我想它至少在技术上是可行的,而且浪费至少可以忽略不计。您可以编写一个函数,在第一次调用时实例化一个类,将其存储在全局中,并在后续调用中返回全局(但是您必须担心线程,这不是您已经做的问题)它)。您可以创建一个类,其__init__
方法引发 TypeError,以便它根本无法实例化,并使用类方法或静态方法执行所有操作,将所需的所有状态保留在类本身上。甚至可以创建一个每次都返回相同实例的类。所有这些的结果是,您从模块中获取一个对象,然后在代码中使用该对象,并且之后使用它的方式看起来是相同的。
我认为您应该在您的一个模块中内联实例化您的类,就像您发布的代码一样,因为它有效,它是一种常见模式,它是明智的,并且对您有意义。
没有理由删除您导入的模块。它不会为你节省任何东西。该模块一旦导入就永远存在(除非您主动做一些奇怪的事情来摆脱它),并且全局变量并不是您需要保存的宝贵资源。
__init__.py,
只要您在内部使用相对名称(即别名而不是 root.tools.aliases)引用模块,就不会通过将模块导入到内部来引入循环依赖关系。循环依赖是一个真正的问题,所以要小心。只要您的模块仅导入树中更深层次的内容,并且您认为这些内容是“较低级别”的(意味着这些较低级别的模块不会导入可能使用它们的较高级别的内容),你应该没事。我会警告不要放入任何实质性代码__init__.py,
,但我认为如果您希望实例所在的位置,实例化您的类就可以了。
归档时间: |
|
查看次数: |
3170 次 |
最近记录: |