#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. Хотя эта ссылка может дать ответ на вопрос, лучше включить основные части ответа здесь и предоставить ссылку для справки. Ответы только по ссылкам могут стать недействительными, если страница, на которую дана ссылка, изменится.