You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python重复实例校验失效:相同Amenity仍被添加至列表

问题排查:Amenity实例重复检测失效的原因及修复

问题描述

Room类的addAmenity方法意图检测重复的Amenity实例,若存在则返回"Duplicate found",否则添加至列表。但实际执行时,属性完全一致的room2Amenity4仍被添加,输出与预期不符。

原代码

class Amenity():
  def __init__(self, itemCode, description, price):
    self._itemCode = itemCode
    self._description = description
    self._price = price

  def __str__(self):
    return "{}, {}, ${:.2f}".format(self._itemCode, self._description, self._price)

class Room():
  def __init__(self):
    self._amenities = []

  def addAmenity(self, newItem):
    if newItem in self._amenities:
      return "Duplicate found"
    else:
        self._amenities.append(newItem)

  def __str__(self):
    amenityListing = "\n".join(str(amenity) for amenity in self._amenities)
    return "{} ".format(amenityListing)

def main():
    room2 = Room()
    room2Amenity1 = Amenity("GYM-PEP","Per entry pass to gym (Level 4-01)",1.00)
    room2Amenity2 = Amenity("FRIDGE","Mini Fridge (50L)",4.59)
    room2Amenity3 = Amenity("WI-FI","One-day Wi-Fi access",1.00)
    room2Amenity4 = Amenity("GYM-PEP","Per entry pass to gym (Level 4-01)",1.00)
    room2.addAmenity(room2Amenity1)
    room2.addAmenity(room2Amenity2)
    room2.addAmenity(room2Amenity3)
    print(room2)
    print()
    room2.addAmenity(room2Amenity4)
    print(room2)

实际输出

GYM-PEP, Per entry pass to gym (Level 4-01), $1.00
FRIDGE, Mini Fridge (50L), $4.59
WI-FI, One-day Wi-Fi access, $1.00 

GYM-PEP, Per entry pass to gym (Level 4-01), $1.00
FRIDGE, Mini Fridge (50L), $4.59
WI-FI, One-day Wi-Fi access, $1.00
GYM-PEP, Per entry pass to gym (Level 4-01), $1.00

预期输出

GYM-PEP, Per entry pass to gym (Level 4-01), $1.00
FRIDGE, Mini Fridge (50L), $4.59
WI-FI, One-day Wi-Fi access, $1.00

Duplicate found
GYM-PEP, Per entry pass to gym (Level 4-01), $1.00
FRIDGE, Mini Fridge (50L), $4.59
WI-FI, One-day Wi-Fi access, $1.00

问题原因

Python中,in运算符判断对象是否存在于列表时,会调用对象的__eq__方法进行相等性比较。自定义类默认的__eq__方法是比较对象的内存地址(即判断是否为同一个实例),而非比较对象的属性值。

room2Amenity1和room2Amenity4虽然属性完全一致,但它们是两个独立的实例,内存地址不同,因此newItem in self._amenities会返回False,导致重复实例被添加。

解决方案

给Amenity类重写__eq__方法,基于对象的属性值来判断相等性。同时,为了遵循Python的最佳实践,建议一并重写__hash__方法(当对象需要存入集合或作为字典键时,hash值需与__eq__逻辑保持一致)。

修改后的代码

class Amenity():
  def __init__(self, itemCode, description, price):
    self._itemCode = itemCode
    self._description = description
    self._price = price

  def __str__(self):
    return "{}, {}, ${:.2f}".format(self._itemCode, self._description, self._price)

  def __eq__(self, other):
    # 先判断是否为Amenity类型
    if not isinstance(other, Amenity):
        return False
    # 比较所有关键属性
    return (self._itemCode == other._itemCode and
            self._description == other._description and
            self._price == other._price)

  def __hash__(self):
    # 基于参与相等性比较的属性生成hash值
    return hash((self._itemCode, self._description, self._price))

class Room():
  def __init__(self):
    self._amenities = []

  def addAmenity(self, newItem):
    if newItem in self._amenities:
      return "Duplicate found"
    else:
        self._amenities.append(newItem)

  def __str__(self):
    amenityListing = "\n".join(str(amenity) for amenity in self._amenities)
    return amenityListing

def main():
    room2 = Room()
    room2Amenity1 = Amenity("GYM-PEP","Per entry pass to gym (Level 4-01)",1.00)
    room2Amenity2 = Amenity("FRIDGE","Mini Fridge (50L)",4.59)
    room2Amenity3 = Amenity("WI-FI","One-day Wi-Fi access",1.00)
    room2Amenity4 = Amenity("GYM-PEP","Per entry pass to gym (Level 4-01)",1.00)
    room2.addAmenity(room2Amenity1)
    room2.addAmenity(room2Amenity2)
    room2.addAmenity(room2Amenity3)
    print(room2)
    print()
    result = room2.addAmenity(room2Amenity4)
    print(result)
    print()
    print(room2)

修改后输出

GYM-PEP, Per entry pass to gym (Level 4-01), $1.00
FRIDGE, Mini Fridge (50L), $4.59
WI-FI, One-day Wi-Fi access, $1.00

Duplicate found

GYM-PEP, Per entry pass to gym (Level 4-01), $1.00
FRIDGE, Mini Fridge (50L), $4.59
WI-FI, One-day Wi-Fi access, $1.00

内容的提问来源于stack exchange,提问作者Long Feng Ho

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 22:24:58