Ошибка при вызове абстрактного класса?

Возникает ошибка при использовании абстрактного метода, моя задача состояла в том, чтобы сделать абстрактный метод, который дальше будет переопределен, но возникает ошибка: 'Flat' object has no attribute 'every_month'

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

from abc import ABC, abstractmethod


class City:
    def __init__(self):
        self.name_city = ' '

    def get_name(self):
        return self.name_city

    def set_name(self, name_city):
        self.name = name_city


class Building:
    def __init__(self):
        self.name_street = ' '
        self.house_number = 0
        self.square = 0
        self.payment = 0

    def get_name_street(self):
        return self.name_city

    def get_house_number(self):
        return self.house_number

    def get_square(self):
        return self.square

    def get_payment(self):
        return self.payment

    def set_name_street(self, name_city):
        self.name_city = name_city

    def set_house_number(self, house_number):
        self.house_number = house_number

    def set_payment(self,payment):
        self.payment = payment

class Room(ABC,Building):
    def __init__(self):
        super().__init__()
        self.number=0
        self.square=0
    def get_number(self):
        return self.number
    def get_square(self):
        return self.square
    def set_number(self,number):
        self.number=number
    def set_square(self,square):
        self.set_square=square
    @abstractmethod
    def every_month_payment(self):
        self.every_month=self.payment*self.square
class Flat(Room):
    def add_people(self,name_people):
        self.name_people=name_people
        self.all_people=[]
        self.all_people.append(self.name_people)
    def get_people(self):
        return self.all_people
    def every_month_payment(self):
        return self.every_month * (1 + len(self.all_people) * 0.1)
class Office(Room):
    def set_name_firm(self,name):
        self.name_firm=name
    def get_name_firm(self):
        return self.name_firm
    def set_type(self,type):
        self.type=type
    def get_type(self):
        return self.type
    def every_month_payment(self):
        return super().every_month * 2
names1=Flat()
names1.set_payment(5)
names1.set_square(6)
names1.add_people('IVANOV')
names1.every_month_payment()```

Ответы (1 шт):

Автор решения: Daniil Loban

Что касается ответа, то его можно было оформить немого по разному, я предпочел такой вариант как наиболее краткий. Если Вы добавляете геттеры и сеттеры для свойств класса то вторым логичным шагом было бы делать и сами свойства или properties, но даже без этого если они есть то думаю их стоит как-то использовать (обычно они предназначены для того, чтобы оградить непосредственное использование переменных класса, добавляя например необходимые проверки в сеттерах и преобразования в геттерах, хотя последнее не обязательно):

class A:
  def __init__(self):
    self._test=0
  def set_test(self, test):
    self._test = test  
  def get_test(self):
    return self._test
  test = property(get_test, set_test)  # добавление свойства

a = A()
print(a.test) # нет необходимости писать a.get_test()
a.test = 5    # нет необходимости писать a.set_test(5)
print(a.test)

В ответе на вопрос я убрал все что не касалось самой сути вопроса чтобы легче было заметить внесенные изменения.

Так же подправил расчет платы, исходя из того, что полагаю чистая плата взимается за одного и +10 % за дополнительного жильца (Вы можете использовать свою формулу, но она считает +10% и для первого жильца, т.е. один жилец будет платить 110% чистой платы):

class Building:
    def __init__(self):
        self._square = 0
        self._payment = 0

    def get_square(self):
        return self._square

    def set_square(self, square):
        # тут может быть проверка
        self._square = square

    def get_payment(self):
        return self._payment

    def set_payment(self, payment):
        # тут может быть проверка
        self._payment = payment

    square = property(get_square, set_square)
    payment = property(get_payment, set_payment) 
        
class Room(Building):
    def __init__(self):
        super().__init__()

    def every_month_payment(self):
        # тут используется доступ уже через геттеры
        return self.payment * self.square

class Flat(Room):
    def __init__(self):
        super().__init__()
        self.all_people=[]

    def add_people(self,name_people):
        self.all_people.append(name_people)

    def get_people(self):
        return self.all_people

    def every_month_payment(self):
        neighbors = len(self.get_people()) - 1 
        return super().every_month_payment() * (
          1 + ((neighbors) * 0.1 if neighbors > 0 else 0)
        ) 

names1=Flat()
names1.set_payment(5)
names1.set_square(6)
print(names1.every_month_payment()) # 30
names1.add_people('IVANOV')
print(names1.every_month_payment()) # 30
names1.add_people('PETROV')
print(names1.every_month_payment()) # 33.0
print(names1.get_people())

В классе Flat методе every_month_payment мы сначала обращаемся к методу every_month_payment в базовом классе а позже используем результат в наших расчетах, но решить эту задачу можно было бы и другими способами если бы у нас был другой не перекрытый классом наследником метод, так или иначе абстрактный метод тут не нужен, тем более как я говорил он не должен иметь реализации.

Абстра́ктный ме́тод — в объектно-ориентированном программировании, метод класса, реализация для которого отсутствует

→ Ссылка