Импортировать другие дочерние классы из того же подмодуля в конструкторе базового класса - PullRequest
0 голосов
/ 05 мая 2020

При следующей структуре папок:

train
|__base
|  |__model.py
|  |__layer.py
|
|__nb
|  |__model.py
|  |__layer.py
|
|__norm
|  |__model.py
|  |__layer.py

nb и norm содержат модели и слои, указанные c с nb и нормальным распределением, соответственно. Классы Model и Layer в этих двух папках являются дочерними по отношению к соответствующим классам в базовой папке. Скажем, экземпляр Model содержит экземпляр Layer, а model.layer, конечно, должен быть из той же папки. Но мне нужно вызвать суперконструктор модели из base.model.py и создать там слой с описанием распределения c.

Я мог бы сделать что-то. вот так в конструкторе базовой модели:

__init__(self, distribution, **kwargs):
    if distribution == 'nb':
        from nb.layer import Layer
    elif distribution == 'norm':
        from norm.layer import Layer
    else:
        assert False, "Unrecognized distribution."
    self.layer = Layer()

Теперь мне нужно знать все распределения в базовой модели и жестко закодировать переданную строку распределения. Но мой инструмент должен быть расширяемым, поэтому я не знаю, какие дополнительные дистрибутивы будут добавлены в будущем. Я хотел бы найти причудливое решение, которое позволит ему автоматически определять, из какой подпапки необходимо импортировать, в зависимости от того, из какой дочерней модели был вызван конструктор базовой модели (т.е. если модель нормы создана, базовая модель также должна импортировать слой норм, а не слой nb).

Есть ли способ обойти это? Идеальное решение будет работать без передачи дополнительных аргументов типа distribution базовому конструктору. Но даже если необходимо передать distribution, можно ли каким-то образом передать правильный путь к подпапке nb / norm и сделать что-то. например from <distribution>.layer import Layer?

1 Ответ

0 голосов
/ 05 мая 2020

Один из способов сделать это - использовать importlib.import_module:

from importlib import import_module


class Model:
    __init__(self, distribution_module: str):
        layers = import_module(name='...' + distribution_module + '.layers', package=__name__)
        self.layer = layers.Layer()

distribution_module должно быть названо после подмодуля (то есть 'norm' или 'nb' в этом случае). В зависимости от структуры папки относительный путь относительно package должен быть дополнен точками (например, в данном случае «...», потому что __name__ - это «train.base.model»). Также можно отказаться от аргумента package, если указан абсолютный путь.

См. Документацию: https://docs.python.org/3/library/importlib.html#importlib .import_module

...