不确定是否有一种巧妙的处理方式,我可以直观地将每个对象/类放入一个共同包装下的自己的模块中。
例如:
__init__.py
AbstractSetting.py
Float.py
String.py
每个模块中的每个类都与模块具有相同的名称,目前我一直这样做:
import Settings
mysetting = Settings.Float.Float()
..这给了我这些双重" Float"名。
我能做到,在包的__init__.py
中:
from Float import Float
..以便我可以这样做:
import Settings
mysetting = Settings.Float()
但我希望这个软件包能够动态更新到我放在其中的任何模块。所以第二天,当我添加" Knob.py"对于这个包,我可以这样做:
import Settings
myknob = Settings.Knob()
有道理吗?
但是,我再也没有使用过包装,并且仍然试图将它包裹起来并尝试尽可能简单。在这一点上,我发现将一个大型主模块中的所有类更容易变得越来越麻烦。
也许包裹不是要走的路?我有哪些替代方案?
非常感谢。
编辑:我想这样做的主要原因是让用户编写自己的模块,这些模块将与应用程序的其余部分集成。本地"插件"建筑,如果你愿意的话。
每个模块将包含一个由具有默认值的超类继承的类。然后,该应用程序具有可用模块的浏览器,单击该模块时,将显示模块属性下的相关信息。然后包含的每个类都有一个类似的接口,应用程序可以使用它。
我做了一些进一步的阅读,显然这不是要走的路。我很想听听你的想法,但这种方法的好处/缺点是什么。
答案 0 :(得分:3)
你应该知道这不是Python的方式。 “每个文件一个类”是一个Java语言,不适用于Python世界。我们通常将模块命名为小写并将相关的类命名为同一个文件(在您的示例中,所有类都将进入settings.py
或从那里明确导入)。但我想你希望用户提供插件的事实是你的方法的合理原因(我认为immdbg以同样的方式做到这一点)。
所以,如果你真的想这样做,你可以把这样的东西放到Settings/__init__.py
:
import os
import glob
import imp
for f in glob.glob(os.path.join(os.path.dirname(__file__), '*.py')):
modname = os.path.basename(f)[:-3]
if modname.startswith('__'): continue
mod = imp.load_source(modname, f)
globals()[modname] = getattr(mod, modname)
# or if you just want to import everything (even worse):
#for name in dir(mod):
# if name.startswith('__'): continue
# globals()[name] = getattr(mod, name)
你能感觉到Python开发人员不希望你这样做吗? :)
答案 1 :(得分:2)
有许多插件系统。例如,一个这样的系统的名称yapsy
(又一个插件系统)。
您可以创建一个提供必要界面的对象:
class Settings(object):
def __getattr__(self, attr):
return load_plugin(attr)
settings = Settings()
在您的代码中:
from settings import settings
knob = settings.Knob()
您可以对load_plugin()
使用您喜欢的任何实现,例如,问题的代码:
from importlib import import_module
def load_plugin(name):
m = import_module('Settings.'+name)
return getattr(m, name)