Игнорируются геттеры и сеттеры

Наги

Пользователь
Пользователь
Окт 25, 2020
74
5
8
Всем добрый день! Вот есть у меня такой код. В нем надо, чтоб в дочерних классах PaperBook и AudioBook pages и duration (атрибуты, которых нет в базовом классе Book) задавались при инициализации экземпляров этих классов. И вроде я так и сделала, но теперь почему-то свои проверки не отрабатывают сеттеры. Ну, условно, должно быть невозможно задать отрицательное значение pages, как прописано в сеттере. Но по факту - можно, т.к. к сеттеру вообще не идет обращение у программы.

Python:
class Book:

    def __init__(self, name: str, author: str):
        self._name = name
        self._author = author

    def __str__(self):
        return f"Книга {self._name}. Автор {self._author}"

    def __repr__(self):
        return f"{self.__class__.__name__}(name={self._name!r}, author={self._author!r})"


class PaperBook(Book):
    def __init__(self, name: str, author: str, pages: int):
        super().__init__(name, author)
        self._pages = pages

    @property
    def pages(self):
        return self._pages

    @pages.setter
    def pages(self, pages: int):
        if not isinstance(pages, int):
            raise TypeError("Количество страниц должно быть типа int")
        if pages <= 0:
            raise ValueError("Количество страниц должно быть положительным числом")
        self._pages = pages

    def __str__(self):
        return f"Книга {self._name}. Автор {self._author}. Объем {self._pages} страниц."

    def __repr__(self):
        return f"{self.__class__.__name__}(name={self._name!r}, author={self._author!r}, pages={self._pages})"


class AudioBook(Book):
    def __init__(self, name: str, author: str, duration: float):
        super().__init__(name, author)
        self._duration = duration

    @property
    def duration(self):
        return self._duration

    @duration.setter
    def duration(self, duration: float):
        if not isinstance(duration, float):
            raise TypeError("Продолжительность должна быть типа float")
        if duration <= 0:
            raise ValueError("Продолжительность должна быть положительным числом")
        self._duration = duration

    def __str__(self):
        return f"Книга {self._name}. Автор {self._author}. Продолжительность {self._duration} часов."

    def __repr__(self):
        return f"{self.__class__.__name__}(name={self._name!r}, author={self._author!r}, duration={self._duration})"


book1 = PaperBook('A Byte of Python', 'Swaroop Chitlur', 164)

book2 = AudioBook('Начала Python', 'Петр Питонов', 999.9)

print(book1.__str__())
print(book1.__repr__())

print()

print(book2.__str__())
print(book2.__repr__())


P.S. Приведу для примера другой код (простите, что длинный), где я поступила иначе с геттерами и сеттерами и там все работает.... но в коде выше мне надо как-то не так( А как - запуталась((
Python:
class BaseDog:
    """Создание и подготовка к работе базового класса Собака"""
    def __init__(self):
        """
        Здесь и далее все атрибуты являются защищенными, так как данные по собакам после занесения доступны только
        в режиме чтения, для ознакомления, но не для редактирования
        :param name: имя собаки
        :param size: высота в холке собаки в метрах
        :param purpose: назначение собаки
        """
    @property
    def name(self):
        """Создание геттера для атрибута name"""
        return self._name

    @name.setter
    def name(self, name: str):
        """Создание cеттера для атрибута name с проверкой name на то, что он состоит из 1-200 букв"""
        if not name.isalpha():
            raise TypeError("Имя должно состоять из букв!")
        if 0 <= len(name) > 200:
            raise ValueError("Длина имени должна быть в пределах 1-200 букв!")
        self._name = name

    @property
    def size(self):
        """Создание геттера для атрибута size"""
        return self._size

    @size.setter
    def size(self, size: float):
        """Создание cеттера для атрибута size с проверкой size на то, что он является положительным числом с
        плавающей точкой, не большим 2"""
        if not isinstance(size, float):
            raise TypeError("Высота в холке должна быть типа float!")
        if 0 <= size >= 2:
            raise ValueError("Высота в холке должна быть больше 0 и меньше 2 метров!")
        self._size = size

    @property
    def purpose(self):
        """Создание геттера для атрибута purpose"""
        return self._purpose

    @purpose.setter
    def purpose(self, purpose: str):
        """Создание cеттера для атрибута purpose с проверкой purpose на то, что он является одной из заданных в
        списке purposes строк"""
        purposes = ['охотничья', 'служебная', 'терьер', 'декоративная', 'пастушья']
        if purpose not in purposes:
            raise ValueError("Неверное назначение!")
        self._purpose = purpose

    def __str__(self) -> str:
        """Создание метода, выводящего информацию о собаке в удобочитаемом формате"""
        return f"Собака: {self._name}. Высота в холке: {self._size} м. Назначение: {self._purpose}."

    def __repr__(self) -> str:
        """Создание метода, выводящего «официальный» текстовый образ объекта, который можно использовать для
        воссоздания этого объекта"""
        return f"{self.__class__.__name__}(name={self._name!r}, size={self._size!r}, purpose={self._purpose!r}"

    def size_in_feet(self) -> float:
        """Создание метода, переводящего значение высоты собаки в холке size из метров в футы; на случай
        использования информации на территориях, использующих американскую систему измерения"""
        return self.size * 3.28084

    def capitalize_name(self) -> str:
        """Создание метода, переводящего имя собаки name в слово, начинающееся с заглавной буквы с последующими
        строчными буквами; на случай, если будет ошибочно занесено иное"""
        return self.name.capitalize()


class FrenchBulldog(BaseDog):
    """Создание и подготовка к работе производного класса Французский бульдог"""
    def __init__(self):
        """
        :param name: наследуется от базового класса Собака
        :param size: наследуется от базового класса Собака
        :param purpose: наследуется от базового класса Собака
        """
        super().__init__()


class AfghanHound(BaseDog):
    """Создание и подготовка к работе производного класса Афганская борзая"""
    def __init__(self):
        """
        :param name: наследуется от базового класса Собака
        :param size: наследуется от базового класса Собака
        :param purpose: наследуется от базового класса Собака
        :param tail_length: длина хвоста собаки в метрах
        :param tail_shape: форма хвоста собаки
        """
        super().__init__()

    @property
    def tail_length(self):
        """Создание геттера для атрибута tail_length"""
        return self._tail_length

    @tail_length.setter
    def tail_length(self, tail_length: float):
        """Создание cеттера для атрибута tail_length с проверкой tail_length на то, что он является положительным
        числом с плавающей точкой, не большим 1"""
        if not isinstance(tail_length, float):
            raise TypeError("Длина хвоста должна быть типа float!")
        if 0 <= tail_length >= 1:
            raise ValueError("Длина хвоста должна быть больше 0 и меньше 1 метра!")
        self._tail_length = tail_length

    @property
    def tail_shape(self):
        """Создание геттера для атрибута tail_shape"""
        return self._tail_shape

    @tail_shape.setter
    def tail_shape(self, tail_shape: str):
        """Создание cеттера для атрибута tail_shape с проверкой tail_shape на то, что он является одним из заданных в
        списке shapes строк"""
        shapes = ['саблевидный', 'крючок', 'полено', 'перо', 'прут', 'серп', 'кольцо', 'двойное кольцо']
        if tail_shape not in shapes:
            raise ValueError("Неверная форма хвоста!")
        self._tail_shape = tail_shape

    def __str__(self) -> str:
        """Перегрузка метода, выводящего информацию о собаке в удобочитаемом строковом формате, так как в вывод
        добавляются два новых параметра: tail_length и _tail_shape"""
        return f"Собака: {self._name}. Высота в холке: {self._size} м. Назначение: {self._purpose}. " \
               f"Длина хвоста: {self._tail_length} м. Форма хвоста: {self._tail_shape}."

    def __repr__(self) -> str:
        """Перегрузка метода, выводящего «официальный» текстовый образ объекта, который можно использовать для
        воссоздания этого объекта, так как в вывод добавляются два новых параметра: tail_length и _tail_shape"""
        return f"{self.__class__.__name__}(name={self._name!r}, size={self._size!r}, purpose={self._purpose!r}, " \
               f"tail_length={self._tail_length!r}, tail_shape={self._tail_shape!r}"

    def capitalize_name(self) -> str:
        """Перегрузка метода, переводящего имя собаки name в слово, начинающееся с заглавной буквы с последующими
        строчными буквами. Теперь метод переводит имя собаки name в слово, состоящее из одних заглавных букв. Это
        сделано с целью визуального выделения охотничьих пород собак среди других"""
        return self.name.upper()


dog1 = FrenchBulldog()
dog1.name = 'арни'
dog1.size = 0.381
dog1.purpose = 'декоративная'

dog2 = AfghanHound()
dog2.name = 'Шелли'
dog2.size = 0.607
dog2.purpose = 'охотничья'
dog2.tail_length = 0.303
dog2.tail_shape = 'серп'

print(dog1.__str__())
print(dog1.__repr__())
print(round(dog1.size_in_feet(), 2), 'ф.,', dog1.capitalize_name())

print()

print(dog2.__str__())
print(dog2.__repr__())
print(round(dog2.size_in_feet(), 2), 'ф.,', dog2.capitalize_name())
 

regnor

Модератор
Команда форума
Модератор
Июл 7, 2020
2 661
474
83
при объявлении в init нижнее подчеркивание не нужно
Python:
class PaperBook(Book):
    def __init__(self, name: str, author: str, pages: int):
        super().__init__(name, author)
        self.pages = pages
и
Python:
class AudioBook(Book):
    def __init__(self, name: str, author: str, duration: float):
        super().__init__(name, author)
        self.duration = duration
 
  • Мне нравится
Реакции: Наги

Наги

Пользователь
Пользователь
Окт 25, 2020
74
5
8
при объявлении в init нижнее подчеркивание не нужно
Python:
class PaperBook(Book):
    def __init__(self, name: str, author: str, pages: int):
        super().__init__(name, author)
        self.pages = pages
и
Python:
class AudioBook(Book):
    def __init__(self, name: str, author: str, duration: float):
        super().__init__(name, author)
        self.duration = duration
Спасибо!! Все было так просто) Вы меня неизменно спасаете ^^
 

Форум IT Специалистов