Python自定义mySet类测试不通过,请求问题排查
问题:自定义mySet集合类与测试程序不兼容
我从零构建了Python的mySet集合类,无编码错误,但无法输出测试程序的预期结果。以下是我的mySet类代码:
class mySet: def __init__(self, data = None): if data == None: self.elements = [] else: self.elements = [] if len(data) > 1: for i in data: if i not in self.elements: self.elements.append(i) def add(self, data): if data not in self.elements: self.elements.append(data) def pop(self): if len(self.elements) > 0: return self.elements.pop() raise KeyError('empty set!') def remove(self, key): if key in self.elements: self.elements.remove(key) else: raise KeyError('This value was not found in the set') def discard(self, key): if key in self.elements: self.elements.remove(key) def clear(self): if len(self.elements) > 0: self.elements.clear() def copy(self): from copy import copy return copy(self) def issubset(self, otherSet): return self.__le__(otherSet) def ispropersubset(self, otherSet): return self.__lt__(otherSet) def issuperset(self, otherSet): return self.__ge__(otherSet) def ispropersuperset(self, otherSet): return self.__gt__(otherSet) def union(self, otherSet): return self.__or__(otherSet) def intersection(self, otherSet): return self.__and__(otherSet) def difference(self, otherSet): return self.__sub__(otherSet) def symmetric_difference(self, otherSet): return self.__xor__(otherSet) def isdisjoint(self, otherSet): if len(self.__xor__(otherSet)) == 0: return True return False def update(self, otherSet): self.__ior__(otherSet) def intersection_update(self, otherSet): self.__iand__(otherSet) def difference_update(self, otherSet): self.__isub__(otherSet) def symmetric_difference_update(self, otherSet): self.__ixor__(otherSet) def __str__(self): return f'{self.elements}' def __repr__(self): return self.__str__() def __len__(self): return len(self.elements) def __contains__(self, key): if key in self.elements: return True return False def __eq__(self, other): if isinstance(other, mySet): if self.elements == other.elements: return True return False return False def __ne__(self, other): if isinstance(other, mySet): if self.elements != other.elements: return True return False return False def __le__(self, other): if isinstance(other, mySet): if self.elements <= other.elements: return True return False return False def __lt__(self, other): if isinstance(other, mySet): if self.__le__(other) and self.__ne__(other): return True return False return False def __ge__(self, other): if isinstance(other, mySet): if self.elements >= other.elements: return True return False return False def __gt__(self, other): if isinstance(other, mySet): if self.__ge__(other) and self.__ne__(other): return True return False return False def __or__(self, other): if isinstance(other, mySet): result = self.copy() for i in other.elements: result.add(i) return result def __and__(self, other): if isinstance(other, mySet): result = mySet() for i in self.elements: if i in other.elements: result.add(i) return result def __sub__(self, other): if isinstance(other, mySet): result = mySet() for i in self.elements: if i not in other.elements: result.add(i) return result def __xor__(self, other): if isinstance(other, mySet): result = mySet() for i in other.elements: if i not in self.elements: result.add(i) for j in self.elements: if j not in other.elements: result.add(j) return result def __ior__(self, other): self.add(other.elements) def __iand__(self, other): result = self.__and__(other) self.elements = result def __isub__(self, other): result = self.__sub__(other) self.elements = result def __ixor__(self, other): result = self.__xor__(other) self.elements = result
运行测试程序后得到如下错误:
Error: init 7. Expected: [1, 2, 3], Got: [1, 3, 2] Error: init 8. Expected: [1, 2, 3], Got: [1, 3, 2] Error: init 10. Expected: [1, 2, 3], Got: [1, 3, 2] Error: init 12. Expected: True, Got: False Error: euqals 2. Expected: True, Got: False Error: euqals 5. Expected: False, Got: True Error: isdisjoint 1. Expected: True, Got: False Error: isdisjoint 2. Expected: True, Got: False Error: isdisjoint 5. Expected: True, Got: False Error: isdisjoint 6. Expected: True, Got: False Error: add 1. Expected: [], Got: [1] Error: add 2. Expected: [4, 2, 1, 3], Got: [1, 2, 3, 4] Error: update 1A. Expected: [1, 2, 3, 4, 5], Got: [1, 2, 3, [3, 4, 5]] Error: update 2A. Expected: [1, 2, 3], Got: [[1, 2, 3]] Error: update 3A. Expected: [1, 2, 3], Got: [1, 2, 3, []] Error: update 4A. Expected: [1, 2, 3], Got: [1, 2, 3, [1, 2, 3]] Error: union 2A. Expected: [2, 3, 4, 5, 6], Got: [4, 5, 6, 2, 3, 4, 5] Error: union 3A. Expected: [4, 5, 6], Got: [4, 5, 6, 2, 3, 4, 5] Error: union 4A. Expected: [4, 5, 6], Got: [4, 5, 6, 2, 3, 4, 5, 4, 5, 6, 2, 3, 4, 5] Error: union 1B. Expected: [1, 2, 3, 4, 5, 6], Got: [1, 2, 3, 4, 5, 6, 4, 5, 6, 2, 3, 4, 5, 4, 5, 6, 2, 3, 4, 5] Error: union 2B. Expected: [2, 3, 4, 5, 6], Got: [4, 5, 6, 2, 3, 4, 5, 4, 5, 6, 2, 3, 4, 5, 2, 3, 4, 5] Error: union 3B. Expected: [4, 5, 6], Got: [4, 5, 6, 2, 3, 4, 5, 4, 5, 6, 2, 3, 4, 5, 4, 5, 6, 2, 3, 4, 5, 2, 3, 4, 5] Error: union 4B. Expected: [4, 5, 6], Got: [4, 5, 6, 2, 3, 4, 5, 4, 5, 6, 2, 3, 4, 5, 2, 3, 4, 5, 4, 5, 6, 2, 3, 4, 5, 4, 5, 6, 2, 3, 4, 5, 4, 5, 6, 2, 3, 4, 5, 2, 3, 4, 5] Error: difference 2A. Expected: [], Got: [1] Error: difference 2B. Expected: [], Got: [1] Error: symmetric_difference 1A. Expected: [1, 2, 3, 4, 5, 6], Got: [4, 5, 6, 1, 2, 3] Error: symmetric_difference 2A. Expected: [1, 4, 5], Got: [4, 5, 1] Error: symmetric_difference 1B. Expected: [1, 2, 3, 4, 5, 6], Got: [4, 5, 6, 1, 2, 3] Error: symmetric_difference 2B. Expected: [1, 4, 5], Got: [4, 5, 1] Error: discard 2. Expected: [3, 2], Got: [2, 3] 177 tests run. 30 errors found
问题分析与修复方案
从错误信息和代码来看,核心问题集中在集合无序性处理、初始化逻辑漏洞、原地操作错误、相等性判断逻辑错误这几个方面,逐个修复如下:
1. 初始化方法__init__漏洞修复
原代码中if len(data) > 1:的判断会忽略长度为1的输入,比如mySet([1])会得到空列表。同时测试预期元素按升序排列,所以初始化后需要对元素排序:
def __init__(self, data=None): self.elements = [] if data is not None: for i in data: if i not in self.elements: self.elements.append(i) self.elements.sort()
2. 相等性与子集判断逻辑修复
原代码直接比较列表顺序,不符合集合“元素相同即相等”的特性;子集判断用列表字典序比较也不正确,需改为基于元素存在性的判断:
def __eq__(self, other): if not isinstance(other, mySet): return False return set(self.elements) == set(other.elements) def __ne__(self, other): return not self.__eq__(other) def __le__(self, other): if not isinstance(other, mySet): return False for elem in self.elements: if elem not in other.elements: return False return True def __ge__(self, other): if not isinstance(other, mySet): return False return other.__le__(self)
3. 原地操作方法修复
__ior__原代码将整个列表作为单个元素添加,需改为逐个添加元素__iand__、__isub__、__ixor__原代码将mySet实例赋值给self.elements,需改为取实例的elements属性
def __ior__(self, other): if isinstance(other, mySet): for elem in other.elements: self.add(elem) return self def __iand__(self, other): if isinstance(other, mySet): result = self.__and__(other) self.elements = result.elements return self def __isub__(self, other): if isinstance(other, mySet): result = self.__sub__(other) self.elements = result.elements return self def __ixor__(self, other): if isinstance(other, mySet): result = self.__xor__(other) self.elements = result.elements return self
4. add、remove、discard方法排序修复
为匹配测试的有序预期,添加或删除元素后需重新排序:
def add(self, data): if data not in self.elements: self.elements.append(data) self.elements.sort() def remove(self, key): if key in self.elements: self.elements.remove(key) self.elements.sort() else: raise KeyError('This value was not found in the set') def discard(self, key): if key in self.elements: self.elements.remove(key) self.elements.sort()
5. isdisjoint方法逻辑修复
原代码用对称差集判断,实际isdisjoint应判断两个集合是否无交集:
def isdisjoint(self, otherSet): if not isinstance(otherSet, mySet): return False return len(self.__and__(otherSet)) == 0
6. pop方法行为调整
原代码弹出列表最后一个元素,测试预期可能是弹出第一个元素,改为弹出排序后的第一个元素:
def pop(self): if len(self.elements) > 0: return self.elements.pop(0) raise KeyError('empty set!')
7. copy方法优化
原代码用浅拷贝可能引发问题,改为手动创建新实例并复制元素:
def copy(self): new_set = mySet() new_set.elements = self.elements.copy() return new_set
修复后的完整mySet类
class mySet: def __init__(self, data=None): self.elements = [] if data is not None: for i in data: if i not in self.elements: self.elements.append(i) self.elements.sort() def add(self, data): if data not in self.elements: self.elements.append(data) self.elements.sort() def pop(self): if len(self.elements) > 0: return self.elements.pop(0) raise KeyError('empty set!') def remove(self, key): if key in self.elements: self.elements.remove(key) self.elements.sort() else: raise KeyError('This value was not found in the set') def discard(self, key): if key in self.elements: self.elements.remove(key) self.elements.sort() def clear(self): self.elements.clear() def copy(self): new_set = mySet() new_set.elements = self.elements.copy() return new_set def issubset(self, otherSet): return self.__le__(otherSet) def ispropersubset(self, otherSet): return self.__lt__(otherSet) def issuperset(self, otherSet): return self.__ge__(otherSet) def ispropersuperset(self, otherSet): return self.__gt__(otherSet) def union(self, otherSet): return self.__or__(otherSet) def intersection(self, otherSet): return self.__and__(otherSet) def difference(self, otherSet): return self.__sub__(otherSet) def symmetric_difference(self, otherSet): return self.__xor__(otherSet) def isdisjoint(self, otherSet): if not isinstance(otherSet, mySet): return False return len(self.__and__(otherSet)) == 0 def update(self, otherSet): self.__ior__(otherSet) def intersection_update(self, otherSet): self.__iand__(otherSet) def difference_update(self, otherSet): self.__isub__(otherSet) def symmetric_difference_update(self, otherSet): self.__ixor__(otherSet) def __str__(self): return f'{self.elements}' def __repr__(self): return self.__str__() def __len__(self): return len(self.elements) def __contains__(self, key): return key in self.elements def __eq__(self, other): if not isinstance(other, mySet): return False return set
相关产品推荐
相关产品推荐

