Всем привет. Требуется помощь в решении задачи

Создайте класс Person, у которого есть: конструктор init, принимающий 3 аргумента: name, surname, gender. Атрибут gender может принимать только 2 значения: "male" и "female", по умолчанию "male". Если в атрибут gender передается любое другое значение, печатать сообщение: "Не знаю, что вы имели ввиду? Пусть это будет мальчик!" и проставить атрибут gender значением "male" переопределить метод str следующим образом: если объект - мужчина (атрибут gender = "male"), возвращать строку "Гражданин <Фамилия> <Имя> если объект - женщина (атрибут gender = "female"), возвращать строку "Гражданка <Фамилия> <Имя>.

class Person:
    def __init__(self, name, surname, gender = 'male'):
        self.name = name
        self.surname = surname
        self.__gender = gender
    
    
    @property
    def gender(self):
        return self.__gender
    
            
    @gender.setter
    def gender(self, value):
        if value in ("male", "female"):
            self.__gender = value
        else:
            print("Не знаю, что вы имели ввиду? Пусть это будет мальчик!")
            self.__gender = "male"
    
    def __str__(self):
        if self.gender == 'male':
            return f"Гражданин {self.surname} {self.name}"
        if self.gender == 'female':
            return f"Гражданка {self.surname} {self.name}"
        
p1 = Person('Chuck', 'Norris')
print(p1) # печатает "Гражданин Norris Chuck"
p2 = Person('Mila', 'Kunis', 'female')
print(p2) # печатает "Гражданка Kunis Mila"
p3 = Person('Оби-Ван', 'Кеноби', 'male')# печатает "Не знаю, что вы имели ввиду?  Пусть это будет мальчик!"
print(p3) # печатает "Гражданин Кеноби Оби-Ван"

Результат:

    Гражданин Norris Chuck
    Гражданка Kunis Mila
    Traceback (most recent call last):
      File "main.py", line 33, in <module>
        print(p3) # печатает "Гражданин Кеноби Оби-Ван"
    TypeError: __str__ returned non-string (type NoneType)

Вопрос: Что я делаю не так? В ООП новичок как и в питоне.


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

Автор решения: 4500zenja

Вы пытаетесь использовать декораторы @property и @gender.setter, которые всё-таки являются обычными геттерами и сеттерами. Они могут использоваться ТОЛЬКО при доступе/занесении данных через уже существующий объект класса и не могут применяться внутри конструктора, если они уже стоят как приватные атрибуты. Если мы будем писать внутри конструктора self.gender, то получатся уже неприватные методы, если снаружи писать, то будет не очень красиво.

Если геттер и можно оставить (хотя и его можно убрать, имхо), то сеттер точно убирать надо.

class Person:
  def __init__(self, name, surname, gender = 'male'):
    self.name = name
    self.surname = surname
    if gender in ("male", "female"):
      self.__gender = gender
    else:
      print("Не знаю, что вы имели ввиду? Пусть это будет мальчик!")
      self.__gender = "male"


  @property
  def gender(self):
    return self.__gender
    
  def __str__(self):
    if self.gender == 'male':
      return f"Гражданин {self.surname} {self.name}"
    if self.gender == 'female':
      return f"Гражданка {self.surname} {self.name}"

p1 = Person('Chuck', 'Norris')
print(p1) # печатает "Гражданин Norris Chuck"
p2 = Person('Mila', 'Kunis', 'female')
print(p2) # печатает "Гражданка Kunis Mila"
p3 = Person('Оби-Ван', 'Кеноби', 'malf') # печатает "Не знаю, что вы имели 
                                         # ввиду? Пусть это будет мальчик!"
print(p3) # печатает "Гражданин Кеноби Оби-Ван"

А вот вариант и без геттера через декораторы:

class Person:
  def __init__(self, name, surname, gender = 'male'):
    self.name = name
    self.surname = surname
    if gender in ("male", "female"):
      self.__gender = gender
    else:
      print("Не знаю, что вы имели ввиду? Пусть это будет мальчик!")
      self.__gender = "male"
    
  def __str__(self):
    if self.__gender == 'male':
      return f"Гражданин {self.surname} {self.name}"
    if self.__gender == 'female':
      return f"Гражданка {self.surname} {self.name}"

p1 = Person('Chuck', 'Norris')
print(p1) # печатает "Гражданин Norris Chuck"
p2 = Person('Mila', 'Kunis', 'female')
print(p2) # печатает "Гражданка Kunis Mila"
p3 = Person('Оби-Ван', 'Кеноби', 'malf')# печатает "Не знаю, что вы имели ввиду? Пусть это будет мальчик!"
print(p3) # печатает "Гражданин Кеноби Оби-Ван"
→ Ссылка