平等覆盖问题

时间:2017-04-23 00:13:31

标签: python dictionary override equality

我是Python的新手,我很困惑为什么我会收到覆盖错误。我正在尝试构建一个类网络并将其表示为由BST表示的字典。字典中的键是学生对象,其值为课程列表,或者是课程(字符串),其值为学生列表。问题在于,在分析课程是否在字典中时,尽管是字符串对象,它仍然使用Student类的相等性。这是我的代码:

def getClassList():
ClassList = []      # an empty list to be filled from class.csv file
with open('lab6.csv', 'rb') as f:  # access local file 'class.csv'
    reader = csv.reader(f)          # connects reader object to file
    for row in reader:              # reads one text line at a time
        ClassList += [row]          # .. and appends to the ClassList
return ClassList

class Student:
  def __init__(self, lastname, firstname, favcolor):
    # assert(True)
    self.lastname = lastname
    self.firstname = firstname
    self.favcolor = favcolor

  def __eq__(self, other):
    assert(type(other) == type(self))
    if (self.lastname == other.lastname and self.firstname == other.firstname and self.favcolor == other.favcolor):
        return True
    else:
        return False

def __repr__(self):
    return str(self.firstname)+' '+str(self.lastname)

class ClassNetwork:
 def __init__(self):
    #creating an empty graph
    self.rep=Dictionary()
    #using the getClassList function to get the necessary info to create the graph
    classlist=getClassList()
    #not using the first list since it doesn't contain info
    classlist=classlist[1:]

    #traversing the list of lists
    for i in range(len(classlist)):
        #constructing a new student from each list (Student object)
        newStudent=Student(classlist[i][0],classlist[i][1],classlist[i][3])
        #getting a course from each list (str type)
        newCourse=str(classlist[i][2])

        #HANDLING THE COURSE
        #checking if the course exists or not
        if self.rep.lookup(newCourse)=='No entry':
            #if not, add it
            self.rep.put(newCourse,[newStudent])
        #if course already exists, update the student list
        else:
            upCo=self.rep.lookup(newCourse)+[newStudent]
            self.rep.put(newCourse,upCo)

        #HANDLING THE STUDENT
        #checking if the student exists or not
        if self.rep.lookup(newStudent)=='No entry':
            #if not, add them - use put method
            self.rep.put(newStudent,[newCourse])
        #if the student already exists, update course list
        else:
            #updated value=old courses+the new course
            upSt=self.rep.lookup(newStudent)+[newCourse]
            self.rep.put(newStudent,upSt)

 def __repr__(self):
    return repr(self.rep.rep.inorderlist())

错误:

Exception raised:
Traceback (most recent call last):
  File "/usr/lib/python2.7/doctest.py", line 1315, in __run
    compileflags, 1) in test.globs
  File "<doctest __main__[0]>", line 1, in <module>
    CN = ClassNetwork()
  File "/homes/user/cs106/Lab 6/lab6.py", line 93, in __init__
    if self.rep.lookup(newStudent)=='No entry':
  File "/homes/user/cs106/Lab 6/lab6.py", line 181, in lookup
    return self.rep.lookup(key)
  File "/homes/user/cs106/Lab 6/BST.py", line 81, in lookup
    elif self.root()[0] == key:
  File "/homes/user/cs106/Lab 6/lab6.py", line 56, in __eq__
    assert(type(other) == type(self))
AssertionError

2 个答案:

答案 0 :(得分:0)

您应该return False而不是assert

def __eq__(self, other):
    if type(other) != type(self):
        return False
    if (self.lastname == other.lastname and self.firstname == other.firstname and self.favcolor == other.favcolor):
        return True
    else:
        return False

如果比较返回assert,则使用AssertionError会抛出False

答案 1 :(得分:0)

正如罗伯特·希曼提到的那样assert如果断言条件为假则会引发AssertionError。发生这种情况时,会打印一条错误消息并终止您的程序。您可能希望这种情况发生。 ;)相反,您应该将other的类型检查作为相等测试中的第一项,如下所示。

断言旨在捕捉程序逻辑中的缺陷:如果assert测试失败,则表明您的程序逻辑错误而您需要修复它。

不是使用assert函数进行类型测试,而是使用type更好,例如

isinstance

它也更灵活:如果if isinstance(other, Student): 是一个派生自other的类,则测试将通过。

不要做

Student

相反,请使用这个更紧凑的版本:

if some_condition: 
    return True 
else: 
    return False

如果return some_condition. 实际上不是布尔值(some_conditionFalse)并且您实际上需要函数返回布尔值,那么您可以

True

将其转换为布尔值,但这通常不是必需的。

此外,您似乎仍在使用Python 2.您应该定义您的类继承自return bool(some_condition) ,否则您将获得旧式类而不是优秀的新式类(在Python 3中类是新式的,因此您不需要显式继承object)。

object方法还有改进的余地。似乎所有Student.__repr__实例属性(Studentlastnamefirstname)都是字符串,因此无需在其上调用favcolor可以使用str连接字符串,但使用+.format方法通常更方便。此外,.join旨在供程序员使用,理想情况下它应返回一个可用于重新构造对象的字符串;使用__repr__创建用户友好的字符串。 (如果某个类定义__str__但未定义__repr__,则在对象上调用__str__时会使用__repr__

以下是str类的改进版本,它在Python 2和Python 3上运行。

Student

输出

from __future__ import print_function

class Student(object):
    def __init__(self, lastname, firstname, favcolor):
        self.lastname = lastname
        self.firstname = firstname
        self.favcolor = favcolor

    def __eq__(self, other):
        return (isinstance(other, Student) and self.lastname == other.lastname 
            and self.firstname == other.firstname and self.favcolor == other.favcolor)

    def __repr__(self):
        return 'Student({!r}, {!r}, {!r})'.format(self.lastname, self.firstname, self.favcolor)

    def __str__(self):
        return '{} {}'.format(self.firstname, self.lastname)

# test

students = [
    Student('Smith', 'John', 'red'),
    Student('Jones', 'Fred', 'blue'),
    'not a student',
]

for s1 in students:
    print(s1)
    for s2 in students:
        print('    {!r} : {}'.format(s2, s1 == s2))