如何在 python3.8+ 中自动化对象初始化

情况

我目前正在做一个小但非常可扩展的项目,我有以下结构:


/

|- main.py

|- services

   |- __init__.py

   |- service1.py 

   |- service2.py

   |- ...

这些服务中的每一个都创建一个对象,它们都具有完全相同的参数,并且它们都以相同的方式使用。他们之间的区别在于内部,他们做一些事情,对于这个不重要的问题,以不同的方式做事。


现在这是围绕我的代码当前如何处理它的方式:


main.py

from services import *


someObject = {} #content doesn't matter, it's always the same

serv_arr = []   # an array to hold all services


serv_arr.append( service1.service1(someObject) ) 

serv_arr.append( service2.service2(someObject) )

...


for service in serv_arr:

    # this function always has the same name and return type in each service

    service.do_something()

问题

我的具体问题是:有没有办法通过serv_arr循环自动创建,这样,如果我添加service100.py和service101.py到包中services,我不必返回main.py并手动添加它,而是自动加载它需要?


慕斯709654
浏览 131回答 2
2回答

呼啦一阵风

好的,基于这个想法:奥斯汀菲尔普的回答# services/__init__.pyfrom .service1 import service1from .service2 import service2...services = [service1, service2, ...]__all__ = ['services']在这个答案中提到的工厂模式中特别公开的方法和模块的想法,我想出了一个非常hacky的解决方案,它不会使全局命名空间混乱(@Austin Philp 批评的另一件事)。解决方案我有了在每个模块中实现一个方法的想法,该方法除了创建所述模块的实例之外什么都不做,并且每个模块都在以下内容中提到services/__init__.py:#services/__init__.pyfrom .service1 import service1from .service2 import service2__all__=["service1", "service2", ...]#services/service1.pyclass service1(object):    def __init__(self, input):        ......# def create_instance(input):    return service1(input) # create the object and return it. 然后在 main.py 中,我只是这样做(它非常hacky,但它有效)#main.pyimport servicesimport sys# use the __all__ method to get module names. actuallyfor name in services.__all__:    service = sys.modules[f'services.{name}'].create_instance( input )    # do whatever with service这样我就可以愉快地做任何需要的事情,而不会弄乱全局命名空间,但仍然可以迭代甚至单独调用模块。要添加/删除模块,我唯一需要编辑的是__all__内部变量中的另一个条目services/__init__.py。它甚至消除了对serv_arr数组的需要,因为services.__all__已经有了我感兴趣的所有名称,并且与使用的模块具有相同的长度。

catspeake

首先,您应该真正避免使用该from xxx import *模式,因为它会使全局命名空间变得混乱。您可以将可用服务列表添加到services/__init__.py像这样的东西# services/__init__.pyfrom .service1 import service1from .service2 import service2...services = [service1, service2, ...]__all__ = ['services']如果这对您来说仍然过于手动,您可以遍历目录并使用importlib它们的路径导入服务。但是,我不禁认为这个问题表明设计不好。您可能需要考虑使用类似工厂模式的东西来实例化各种服务,而不是使用大量单独的模块。实际上,如果您想对所有服务进行小幅更改,那么您将面临许多繁琐的工作。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python