Python: ограничить создание экземпляра
Допустим, у меня есть класс Person:
class Person():
def __init__(self, name, surname, birth, death):
self.name = name
self.surname = surname
self.birth = birth
self.death = death
Экземпляры с одинаковыми именем и фамилией могут существовать только в том случае, если у них непересекаются даты рождения и смерти. Например:
first_instance = Person(name='John', surname='Doe', birth='1980/01/01', death='2010/12/31')
second_instance = Person(name='John', surname='Doe', birth='2011/01/01', death='2060/12/31')
Такой вариант допустим. Но если пользователь введет следующий вариант, нужно поднять ошибку:
first_instance = Person(name='John', surname='Doe', birth='1980/01/01', death='2010/12/31')
second_instance = Person(name='John', surname='Doe', birth='2007/01/01', death='2060/12/31')
Как видите, second_instance.birth < first_instance.death (2007/01/01 < 2010/12/31). Taкого быть не должно. Что-то мне подсказывает, что надо использовать def __new__(), но я не совсем понимаю как это реализовать.
Ответы (2 шт):
Я не очень знаю как это правильно делать в питоне (в каком методе нужно проверять и какое исключение нужно кидать), но вот так вроде работает:
class Person():
person_list = []
def __init__(self, name, surname, birth, death):
self.name = name
self.surname = surname
self.birth = birth
self.death = death
for p in Person.person_list:
if p.name == self.name and p.surname == self.surname and (p.birth <= self.birth <= p.death or self.birth <= p.birth <= self.death):
raise ValueError(f'{self} имеет пересекающееся время жизни с {p}')
Person.person_list.append(self)
def __str__(self):
return f'{self.name} {self.surname} {self.birth}-{self.death}'
first_instance = Person(name='John', surname='Doe', birth='1980/01/01', death='2010/12/31')
second_instance = Person(name='John', surname='Doe', birth='2011/01/01', death='2060/12/31')
third_instance = Person(name='John', surname='Doe', birth='2007/01/01', death='2060/12/31')
На попытке создать третью персону будет выкидывать исключение:
ValueError: John Doe 2007/01/01-2060/12/31 имеет пересекающееся время жизни с John Doe 1980/01/01-2010/12/31
Еще один вариант. Словарь __created недоступен вне класса.
class Person:
__created = []
def __init__(self, name, surname, birth, death):
self.name = name
self.surname = surname
self.birth = birth
self.death = death
self.__check_can_create()
def __check_can_create(self):
for p in self.__created:
if all((p.death == self.death, p.name == self.name, p.surname == self.name, p.birth == self.birth)):
raise ValueError('Can`t create person: Person already exists.')
self.__created.append(self)
Person(1, 1, 1, 1)
Person(1, 1, 1, 2)
Person(1, 1, 1, 3)
Person(1, 2, 3, 1)
Person(1, 1, 1, 2) # ValueError