所以我创建了两个叫做邀请和响应的类。然后,我创建了一个名为Event的类。在Event类中,我必须创建一个函数来查看当前的邀请列表和响应列表,并计算有多少邀请没有响应。
邀请和响应都有一个我在get_pending()方法中使用的“name”属性。
我有一个名为“e”的类实例,如下所示:
e = Event("graduation",[Invitation("A",5),Invitation("B",10),Invitation("C",5),Invitation("D",7)], [Response("A",True,5),Response("B",True,6),Response("C",False,0),Response("D",True,1)])
然后我打印了类方法get_pending:
print(e.count_pending())
这是我使用get_pending()方法的代码:
class Invitation:
def __init__(self, name, num_invited):
self.name = name #str
self.num_invited = num_invited #positive int
def __str__(self):
return ("Invitation('%s', %i)" % (self.name, self.num_invited))
def __repr__(self):
return str(self)
def __eq__(self, other):
if self.name == other.name and self.num_invited == other.num_invited:
return True
def __lt__(self, other):
if self.name < other.name:
return True
elif self.name == other.name:
if self.num_invited < other.num_invited:
return True
class Response:
def __init__(self, name, ans, num_attending):
self.name = name #str
self.ans = ans #bool - T/F
self.num_attending = num_attending #zero or more people
def __str__(self):
return ("Response('%s', %r, %i)" % (self.name, self.ans, self.num_attending))
def __repr__(self):
return str(self)
def __eq__(self, other):
if self.name == other.name and self.ans == other.ans and self.num_attending == other.num_attending:
return True
def __lt__(self, other):
if self.name < other.name:
return True
elif self.name == other.name:
if self.ans < other.ans:
return True
elif self.ans == other.ans:
if self.num_attending < other.num_attending:
return True
class Event:
def __init__(self, title, invites=None, responses=None):
self.title = title #str
self.invites = invites #list
self.responses = responses #list
if self.invites == None:
self.invites = []
if self.responses == None:
self.responses = []
self.invites.sort()
self.responses.sort()
def __str__(self):
return ("""Event('%s', %r, %r)""" % (self.title, self.invites, self.responses))
def __repr__(self):
return str(self)
def __eq__(self, other):
if self.title == other.title and self.invites == other.invites and self.responses == other.responses:
return True
def count_pending(self):
num_pending = 0
lst_noresp = self.invites[:]
for invi in lst_noresp:
if (any(invi.name == resp.name for resp in self.responses)) == True:
lst_noresp.remove(invi)
for invi in lst_noresp:
num_pending += invi.num_invited
return num_pending
e = Event("graduation",[Invitation("A",5),Invitation("B",10),Invitation("C",5),Invitation("D",7)], [Response("A",True,5),Response("B",True,6),Response("C",False,0),Response("D",True,1)])
print(e.count_pending())
我的错误是count_pending()方法只是从邀请列表中删除了一些(邀请名为'A',邀请名为'C')的对象,即使所有邀请都有相应的响应。为什么invi.name == resp.name比较不正常?或者,这甚至是问题吗?
答案 0 :(得分:1)
你有一个经典的问题,即在list
进行迭代时改变它:
for invi in lst_noresp: # Iterating
if (any(invi.name == resp.name for resp in self.responses)) == True:
lst_noresp.remove(invi) # Mutating
虽然没有记录的行为,但实际上,这会导致循环跳过每个被删除元素后面的值(迭代器存储当前索引,remove
将以下元素向下移动,所以当你得到了下一个元素,你绕过了移动到被移除元素所占空间的元素),所以你甚至没有检查你的一半值。迭代self.invites
,并改变lst_noresp
,问题就会消失。
或者,构建新的list
并避免O(n**2)
效果:
lst_noresp = [invi for invi in self.invites
if not any(invi.name == resp.name for resp in self.responses)]
可以避免从list
中间缓慢删除,有利于在构建新list
(O(n)
作品)时进行过滤。