Как автоматизировать инициализацию объекта в python3 .8 + - PullRequest
0 голосов
/ 29 января 2020

Ситуация

В настоящее время я работаю над небольшим, но очень расширяемым проектом, в котором у меня есть следующая структура:

/
|- 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()

Вопрос

Мои данные c вопрос в следующем: есть ли способ автоматизировать создание serv_arr с помощью al oop, такой, что, если я добавлю service100.py и service101.py в пакет services, и мне не придется go вернуться в main.py и добавить его вручную, но вместо этого он автоматически загружает все, что ему нужно?

Ответы [ 2 ]

0 голосов
/ 29 января 2020

Хорошо, опираясь на эту идею:

Ответ Остина Филипа

# services/__init__.py

from .service1 import service1
from .service2 import service2
...

services = [service1, service2, ...]

__all__ = ['services']

И идея специально раскрытых методов и модулей из Factory Pattern , упомянутый в этого ответа , я придумал очень хакерское решение, которое работает без загромождения глобального пространства имен (еще одна вещь, которую критиковал @Austin Philp).

Решение

Мне пришла идея реализовать в каждом модуле метод, который ничего не делает, кроме создания экземпляра указанного модуля, и каждый модуль упоминается в services/__init__.py:

#services/__init__.py
from .service1 import service1
from .service2 import service2

__all__=["service1", "service2", ...]
#services/service1.py
class service1(object):
    def __init__(self, input):
        ...
...
# 
def create_instance(input):
    return service1(input) # create the object and return it. 

Затем в main.py я просто делаю это (это очень хакерски, но это работает)

#main.py
import services
import sys

# use the __all__ method to get module names. actually
for 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__ уже имеет все интересующие меня имена и будет иметь ту же длину, что и используемые модули.

0 голосов
/ 29 января 2020

Во-первых, вам действительно следует избегать использования шаблона from xxx import *, поскольку он загромождает глобальное пространство имен.

Вы можете добавить список доступных служб в services/__init__.py

что-то вроде это возможно

# services/__init__.py
from .service1 import service1
from .service2 import service2
...

services = [service1, service2, ...]

__all__ = ['services']

Если это все еще слишком для вас, вы можете перебрать каталог и использовать importlib для импорта служб по их путям.

Однако я не могу помочь, но думаю, что эта проблема свидетельствует о плохом дизайне. Возможно, вы захотите использовать что-то вроде Factory Pattern для создания различных сервисов, вместо того, чтобы иметь большое количество отдельных модулей. Как бы то ни было, если вы захотите внести небольшие изменения во все службы, у вас впереди много утомительной работы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...