Посмотрите на этот пример:
class Team:
def __init__(self, name, coach):
self.name = name
self.coach = coach
team1 = Team("The Teamsters", "Coachy McCoachFace")
team2 = Team("The Teamsters", "Coachy McCoachFace")
teams = [team1, team2]
print(f"Do team1 and team2 have the same identity?: {id(team1)==id(team2)}")
print(f"id(team1): {id(team1)}")
print(f"id(team2): {id(team2)}")
print(f"Are team1 and team2 equivalent?: {team1==team2}")
is_new_team_in_list = Team("The Teamsters", "Coachy McCoachFace") in teams
print(f"Is a new team with the same content in the list?: {is_new_team_in_list}")
Вывод:
Do team1 and team2 have the same identity?: False
id(team1): 46804752
id(team2): 47020080
Are team1 and team2 equivalent?: False
Is a new team with the same content in the list?: False
Первый оператор print проверяет, имеют ли два объекта команды одинаковую идентичность (если ониодин и тот же объект в памяти - обе переменные team1
и team2
связаны с одним и тем же объектом Team
). Это неверно.
Следующие два оператора печати показывают идентификаторы двух командных объектов - как вы можете видеть, что они разные - поэтому существуют два отдельных командных объекта с одинаковым содержимым.
Следующий оператор печати определяет, используют ли два командных объекта один и тот же контент (если они эквивалентны) - по крайней мере, так он выглядит, поскольку мы используем ==
. Однако, поскольку мы не реализовали магический метод __eq__
для нашего класса Team
, поведение по умолчанию возвращается к сравнению идентичности, которое, как мы уже знаем, будет ложным.
Наконец, последний оператор печатипроверяет, будет ли в списке команд с помощью in
найден новый объект Team с таким же содержимым. Результат снова ложен по тем же причинам, что и выше.
Одним из решений является реализация __eq__
для класса вашей команды:
class Team:
def __init__(self, name, coach):
self.name = name
self.coach = coach
def __eq__(self, other):
if isinstance(other, Team):
return self.name == other.name and self.coach == other.coach
return False
team1 = Team("The Teamsters", "Coachy McCoachFace")
team2 = Team("The Teamsters", "Coachy McCoachFace")
teams = [team1, team2]
print(f"Do team1 and team2 have the same identity?: {id(team1)==id(team2)}")
print(f"id(team1): {id(team1)}")
print(f"id(team2): {id(team2)}")
print(f"Are team1 and team2 equivalent?: {team1==team2}")
is_new_team_in_list = Team("The Teamsters", "Coachy McCoachFace") in teams
print(f"Is a new team with the same content in the list?: {is_new_team_in_list}")
Вывод:
Do team1 and team2 have the same identity?: False
id(team1): 46016240
id(team2): 46936048
Are team1 and team2 equivalent?: True
Is a new team with the same content in the list?: True
Теперь вы получаете желаемое поведение. Обратите внимание, что идентификационные данные объекта Team по-прежнему отличаются, что ожидается. Вы также можете изменить поведение метода __eq__
в соответствии с вашими потребностями. Например, вы можете рассматривать две команды как одинаковые, если совпадают только их имена.