Импорт, зависящий от переменных, в Python

#python

Вопрос:

Я создаю класс, в который мне нужно импортировать внешний класс, но выбор класса для импорта зависит от переменной, которая неизвестна до создания экземпляра класса. Структура файла модуля выглядит следующим образом:

 root
| -myclass.py
| -pg
| | -tabledata.py
| -pandas
| | -tabledata.py
 

Мой класс создан для работы с наборами данных, которые хранятся в нескольких форматах (например, Pandas, Postgresql), и мне нужно импортировать TableData класс в зависимости от используемого внутреннего формата данных.

Я хочу сделать что-то вроде этого

 class MyClass:
    def __init__(self,backend):
        if backend == 'pg':
            from .pg.tabledata import TableData
        elif backend == 'pandas':
            from .pandas.tabledata import TableData
    ...
 

но это, конечно, не позволяет мне ссылаться на класс tableData в другом месте в MyClass. Есть ли правильный способ сделать это?

Комментарии:

1. Под «конечно» вы подразумеваете «я не проверял это, но, конечно, это не должно работать»? Потому что это сработает.

2. Сделал свой пост более конкретным. Импорт работает, но я не могу ссылаться на него в другом месте класса.

Ответ №1:

Просто запомните класс, в который вы импортировали, __init__ и используйте его позже:

 class MyClass:
    def __init__(self, backend):
        if backend == 'pg':
            from sub1.tabledata import TableData
            self.class_to_create = TableData  # Remember the class, do not create an object
        elif backend == 'pandas':
            from sub2.tabledata import TableData
            self.class_to_create = TableData  # Remember the class, do not create an object

    def gimme_a_table(self):
        return self.class_to_create()  # Create an object whenever you need


if __name__ == "__main__":
    m = MyClass("pandas")
    print(m.gimme_a_table())
    n = MyClass("pg")
    print(n.gimme_a_table())
 

Но я все равно предпочел бы видеть импорт в верхней части файла. Вы можете добиться этого, переименовав импорт с as :

 from sub1.tabledata import TableData as PgTable
from sub2.tabledata import TableData as PandasTable


class MyClass:
    def __init__(self, backend):
        if backend == 'pg':
            self.class_to_create = PgTable  # Remember the class, do not create an object
        elif backend == 'pandas':
            self.class_to_create = PandasTable  # Remember the class, do not create an object

    def gimme_a_table(self):
        return self.class_to_create()  # Create an object whenever you need


if __name__ == "__main__":
    m = MyClass("pandas")
    print(m.gimme_a_table())
    n = MyClass("pg")
    print(n.gimme_a_table())
 

Ответ №2:

Возможно, вы можете импортировать и то, и другое, и в соответствии с каким-либо внешним файлом конфигурации или с помощью какого-либо флага, добавленного при запуске кода, вы можете решить, какую функцию вызывать.

Ответ №3:

В пакете importlib есть хороший метод import_module, который поможет в этом. Проверьте https://docs.python.org/3/library/importlib.html#importlib.import_module .

Комментарии:

1. Хотя эта ссылка может дать ответ на вопрос, лучше включить основные части ответа здесь и предоставить ссылку для справки. Ответы только по ссылкам могут стать недействительными, если страница, на которую дана ссылка, изменится.