Всем добрый день! Вот есть у меня такой код. В нем надо, чтоб в дочерних классах PaperBook и AudioBook pages и duration (атрибуты, которых нет в базовом классе Book) задавались при инициализации экземпляров этих классов. И вроде я так и сделала, но теперь почему-то свои проверки не отрабатывают сеттеры. Ну, условно, должно быть невозможно задать отрицательное значение pages, как прописано в сеттере. Но по факту - можно, т.к. к сеттеру вообще не идет обращение у программы.
P.S. Приведу для примера другой код (простите, что длинный), где я поступила иначе с геттерами и сеттерами и там все работает.... но в коде выше мне надо как-то не так( А как - запуталась((
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())