Как предотвратить добавление дубликатов объектов класса в списки Python? - PullRequest
0 голосов
/ 06 октября 2019

Я создаю базу данных спортивной команды, в которой хранится информация о спортивной команде. Одна из проблем, с которой я столкнулся в одном из моих методов, заключалась в невозможности предотвратить повторное добавление одного и того же объекта в список. Я не хочу, чтобы пользователь добавлял одну и ту же информацию дважды, но я не совсем уверен, как решить эту проблему.

Я работаю в Python Tkinter, чтобы создать эту программу.

import tkinter as tk
from tkinter import ttk
from tkinter import messagebox


allTeamlist = []



class Team: 

 def __init__(self, team, coach):
   self.team = team
   self.coach = coach
   self.studentsinTeam = []


class MainScreen:
 def __init__(self):

  self.mainscreen = tk.Tk()
  self.mainscreen.title("GUI")
  self.mainscreen.geometry("700x400")

#####Team Buttons##########
  heading3 = tk.Label(self.mainscreen, text= "Team", foreground = "Red", font=("Arial", 10))
  heading3.pack()

  button6 = tk.Button(self.mainscreen, text = "Add New Team", command= self.ShowScreen6)
  button6.pack()

 def OpenWindow(self):
  tk.mainloop()

 def ShowScreen6(self):
  self.mainscreen.destroy()
  screen6 = AddTeamScreen()

class AddTeamScreen:

 def __init__(self):
  self.Tscreen1 = tk.Tk()
  self.Tscreen1.title("Add Team")
  self.Tscreen1.geometry("700x400")

  self.getTeam = tk.StringVar()
  self.getCoach = tk.StringVar()

  self.teamlabel = tk.Label(self.Tscreen1, text = "Add a new Team")
  self.teamlabel.pack()

  self.teamentry = tk.Entry(self.Tscreen1, textvariable= self.getTeam)
  self.teamentry.pack()

  self.coachlabel = tk.Label(self.Tscreen1, text= "Coach")
  self.coachlabel.pack()

  self.coachentry = tk.Entry(self.Tscreen1, textvariable = self.getCoach)
  self.coachentry.pack()

  self.addbutton = tk.Button(self.Tscreen1, text = "Add Team", command = self.addingteammethod)
  self.addbutton.pack()

 def addingteammethod(self):

  addTeam = self.getTeam.get()
  addCoach = self.getCoach.get()

  newTeamtoAdd = Team(addTeam, addCoach)

  if newTeamtoAdd in allTeamlist: 
   messagebox.showerror("Error", "Exists")

  elif newTeamtoAdd not in allTeamlist:
   allTeamlist.append(newTeamtoAdd)
   messagebox.showinfo("SUCCESS", "ADDED")
   print(allTeamlist)

mainscreen = MainScreen()
mainscreen.OpenWindow()

Я новый программист ООП и Tkinter, поэтому я все еще учусь! Как я могу предотвратить это вхождение?

1 Ответ

0 голосов
/ 06 октября 2019

Посмотрите на этот пример:

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__ в соответствии с вашими потребностями. Например, вы можете рассматривать две команды как одинаковые, если совпадают только их имена.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...