Вызов текущей версии метода класса в Python

У меня есть иерархия наследования с двумя классами:

class TfIdfSimilarity(SimilarityModel):
    @property
    def corpus(self):
        return self.model[self._corpus]

    @property
    def model(self):
        return TfidfModel(self._corpus, dictionary=self._dict)


class LsiSimilarity(TfIdfSimilarity):
    @property
    def corpus(self):
        tfidf_corpus = super().corpus
        return self.model[tfidf_corpus]

    @property
    def model(self):
        tfidf_corpus = super().corpus
        return LsiModel(tfidf_corpus)

Однако это вызывает ошибку бесконечной рекурсии, потому что всякий раз, когда я пытаюсь получить LsiSimilarity#model, он вызывает TfIdfSimilarity#corpus, который затем пытается получить доступ к модели и, таким образом, снова вызывает LsiSimilarity#model.

На самом деле я хочу, чтобы TfIdfSimilarity#corpus вызывал только TfIdfSimilarity#model и никогда не рассматривал версию дочернего класса.

Возможно ли это в Python? (Python 3) Если нет, то как мне лучше структурировать иерархию наследования, при этом предоставляя тот же API через функции corpus и model (которые используются моей основной логикой).

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
0
46
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вы всегда можете указать, какой метод вы хотите вызвать, используя вместо self.method_xy вызов с SpecificClass.method(self, other_arguments).

Сначала я пропустил последствия декоратора свойств и переключился на решение с вызовом __get__ (TfIdfSimilarity.model.__get__(self)), но поскольку это вызов частного метода, мне это решение не понравилось.

Вдохновившись этим Как вызвать свойство базового класса, если это свойство перезаписывается в производном классе?, я нашел способ fget:

Минимальный пример

class Test:
    def __init__(self, text):
        self._text = text

    @property
    def text(self):
        return self._text

class InheritTest(Test):

    @property
    def text(self):
        return "test" + self._text    


test = InheritTest("Test")
print(Test.text.fget(test))
# Test
print(test.text)
# testTest

Вы пробовали это? TfIdfSimilarity.model — это не метод, это имущество. Если вы сделаете это, вам скажут, что это не может быть вызвано.

Patrick Haugh 10.05.2019 15:34

Да, вам нужно «отменить определение» дескриптора свойства, вызвав __get__(self)

Masklinn 10.05.2019 15:37

Я не знал о дополнительном вызове, необходимом для свойств. Сейчас включили дополнительный звонок. Благодаря Масклинну

Sparky05 10.05.2019 15:41
Ответ принят как подходящий

Вы можете получить вызывать дескрипторы напрямую, получив ссылку на дескриптор из класса, а затем вызвав метод __get__ дескриптора:

TfIdfSimilarity.model.__get__(self)

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

Обратите внимание, что хотя это работает для property, это связано с конкретной реализацией property.__get__ (которая возвращает self, если экземпляр не указан) и ни в коем случае не гарантируется для всех дескрипторов (например, в py2 FunctionType.__get__ возвращает несвязанный метод, а не сама функция).

bruno desthuilliers 10.05.2019 15:47

После некоторых поисков я нашел решение без вызова __get__ :)

Sparky05 10.05.2019 17:27

Другие вопросы по теме