У меня есть иерархия наследования с двумя классами:
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 (которые используются моей основной логикой).






Вы всегда можете указать, какой метод вы хотите вызвать, используя вместо 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
Да, вам нужно «отменить определение» дескриптора свойства, вызвав __get__(self)
Я не знал о дополнительном вызове, необходимом для свойств. Сейчас включили дополнительный звонок. Благодаря Масклинну
Вы можете получить вызывать дескрипторы напрямую, получив ссылку на дескриптор из класса, а затем вызвав метод __get__ дескриптора:
TfIdfSimilarity.model.__get__(self)
Если вы обнаружите, что делаете это часто, это может быть признаком того, что вам следует использовать обычные методы вместо свойств.
Обратите внимание, что хотя это работает для property, это связано с конкретной реализацией property.__get__ (которая возвращает self, если экземпляр не указан) и ни в коем случае не гарантируется для всех дескрипторов (например, в py2 FunctionType.__get__ возвращает несвязанный метод, а не сама функция).
После некоторых поисков я нашел решение без вызова __get__ :)
Вы пробовали это?
TfIdfSimilarity.model— это не метод, это имущество. Если вы сделаете это, вам скажут, что это не может быть вызвано.