Как правильно использовать абстрактный класс в следующем случае

#python #abstract-class #abstract

#python #абстрактный класс #аннотация

Вопрос:

Я пытаюсь реализовать код, который исправляет незначительные опечатки в данном слове. Эти слова являются именами собственными, которые либо из списка городов, либо из штатов. Учитывая, что мы знаем, является ли опечатка из города или штата. Я пытаюсь реализовать два класса StateTypo , CityTypo которые являются подклассами базового класса, BaseTypo .

Вот код для BaseTypo и StateTypo :

 from collections import Counter
from abc import ABC, abstractmethod


class BaseTypo(ABC):

    def __init__(self):
        self.WORDS = self.dictionary()
        self.N = sum(self.WORDS.values())

    @abstractmethod
    def dictionary(self):
        return dict()

    def known(self, words):
        """"""
        return set(w for w in words if w in self.WORDS)

    def P(self, word):
        """Calculate probability of the given word"""
        return self.WORDS[word] / self.N

    def correction(self, word):
        """Most probable word"""
        return max(self.candidates(word), key=self.P)

    def candidates(self, word):
        """ Generate possible correct words"""
        return self.known([word]) or self.known(self.edits1(word)) or self.known(self.edits2(word)) or [word]

    def edits1(self, word):
        letters = 'abcdefghijklmnopqrstuvwxyz'
        splits = [(word[:i], word[i:]) for i in range(len(word)   1)]
        deletes = [L   R[1:] for L, R in splits if R]
        transposes = [L   R[1]   R[0]   R[2:] for L, R in splits if len(R) > 1]
        replaces = [L   c   R[1:] for L, R in splits if R for c in letters]
        inserts = [L   c   R for L, R in splits for c in letters]
        return set(deletes   transposes   replaces   inserts)

    def edits2(self, word):
        return (e2 for e1 in self.edits1(word) for e2 in self.edits1(e1))


class StateTypo(BaseTypo):
    def __init__(self):
        super(BaseTypo, self).__init__()
        self.address = 'states.txt'

    def dictionary(self):
        print(self.address)
        with open(self.address, 'r') as file:
            lines = file.readlines()
        lines = [line.strip() for line in lines]
        return Counter(lines)


if __name__ == '__main__':
    a = StateTypo()
    corrected = a.correction('himachal prfadesh')
    print(corrected) # should ideally print himachal pradesh

 

Однако приведенный выше код приводит к следующей ошибке:

 Traceback (most recent call last):
  File "correctTypo.py", line 59, in <module>
    corrected = a.correction('himachal prfadesh')
  File "correctTypo.py", line 25, in correction
    return max(self.candidates(word), key=self.P)
  File "correctTypo.py", line 29, in candidates
    return self.known([word]) or self.known(self.edits1(word)) or self.known(self.edits2(w
ord)) or [word]
  File "correctTypo.py", line 17, in known
    return set(w for w in words if w in self.WORDS)
  File "correctTypo.py", line 17, in <genexpr>
    return set(w for w in words if w in self.WORDS)
AttributeError: 'StateTypo' object has no attribute 'WORDS'

 

Теперь я знаю, что нам действительно не нужен абстрактный класс для реализации этого, но как я могу решить эту проблему, учитывая, что моя первоначальная идея о наличии абстрактного метода в базовом классе сохраняется?

Ответ №1:

super означает супер, он дает вам супер объект.

Вы можете инициализировать базовый класс с помощью super(StateTypo, self).__init__() или BaseTypo.__init__(self) , но не super(BaseTypo, self).__init__() .

И address используется во время инициализации, поэтому он должен быть

 class StateTypo(BaseTypo):
    def __init__(self):
        self.address = 'states.txt'
        super(StateTypo, self).__init__()
 

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