Python 3.14中Mazo类eliminaCarta方法删除指定元素异常问题
这是我在本站的第一个问题。我尝试将Python 2中的eliminaCarta函数适配到Python 3.14,这个函数属于Mazo类,作用是接收Carta类实例并从Mazo的列表中删除该实例。但实际运行时,函数删除的是列表第一个元素而非目标元素,我找不到问题所在。
相关代码如下:
import random class Carta: listaDePalos = ["Tréboles", "Diamantes", "Corazones", "Picas"] listaDeValores = ["nada", "As", "2", "3", "4", "5", "6", "7", "8", "9", "10", "Sota", "Reina", "Rey"] def __init__(self, palo=0, valor=0): self.palo = palo self.valor = valor def __str__(self): return (self.listaDeValores[self.valor] + " de " + self.listaDePalos[self.palo]) def __lt__(self, other): # controlar el palo if self.palo > other.palo: return 1 if self.palo < other.palo: return -1 if self.valor == 1 and self.valor != other.valor: return 1 if other.valor == 1 and self.valor != other.valor: return -1 # si son del mismo palo, controlar el valor if self.valor > other.valor: return 1 if self.valor < other.valor: return -1 # los valores son iguales, es un empate return 0 def __gt__(self, other): # controlar el palo if self.palo > other.palo: return 1 if self.palo < other.palo: return -1 if self.valor == 1 and self.valor != other.valor: return 1 if other.valor == 1 and self.valor != other.valor: return -1 # si son del mismo palo, controlar el valor if self.valor > other.valor: return 1 if self.valor < other.valor: return -1 # los valores son iguales, es un empate return 0 def __eq__(self, other): if self.valor == other.valor: return 1 else: return -1 class Mazo: def __init__(self): self.cartas = [] for palo in range(4): for valor in range(1, 14): self.cartas.append(Carta(palo, valor)) def muestraMazo(self): for carta in self.cartas: print(carta) def __str__(self): s = "" for i in range(len(self.cartas)): s = s + " "*i + str(self.cartas[i]) + "\n" return s def mezclar(self): nCartas = len(self.cartas) for i in range(nCartas): j = random.randrange(i, nCartas) self.cartas[i], self.cartas[j] = self.cartas[j], self.cartas[i] def __contains__(self, item): return item in self.items def eliminaCarta(self, carta): if carta in self.cartas: self.cartas.remove(carta) return 1 else: return 0
初始打印Mazo实例时输出正常:
As de Tréboles 2 de Tréboles 3 de Tréboles 4 de Tréboles 5 de Tréboles 6 de Tréboles 7 de Tréboles 8 de Tréboles 9 de Tréboles 10 de Tréboles Sota de Tréboles Reina de Tréboles Rey de Tréboles As de Diamantes 2 de Diamantes 3 de Diamantes 4 de Diamantes 5 de Diamantes 6 de Diamantes 7 de Diamantes 8 de Diamantes 9 de Diamantes 10 de Diamantes Sota de Diamantes Reina de Diamantes Rey de Diamantes As de Corazones 2 de Corazones 3 de Corazones 4 de Corazones 5 de Corazones 6 de Corazones 7 de Corazones 8 de Corazones 9 de Corazones 10 de Corazones Sota de Corazones Reina de Corazones Rey de Corazones As de Picas 2 de Picas 3 de Picas 4 de Picas 5 de Picas 6 de Picas 7 de Picas 8 de Picas 9 de Picas 10 de Picas Sota de Picas Reina de Picas Rey de Picas
但执行以下代码:
carta = Carta(1,13) mazo = Mazo() mazo.eliminaCarta(carta) print(mazo)
结果却删除了列表第一个元素(As de Tréboles),而本应删除的是Rey de Diamantes:
2 de Tréboles 3 de Tréboles 4 de Tréboles 5 de Tréboles 6 de Tréboles 7 de Tréboles 8 de Tréboles 9 de Tréboles 10 de Tréboles Sota de Tréboles Reina de Tréboles Rey de Tréboles As de Diamantes 2 de Diamantes 3 de Diamantes 4 de Diamantes 5 de Diamantes 6 de Diamantes 7 de Diamantes 8 de Diamantes 9 de Diamantes 10 de Diamantes Sota de Diamantes Reina de Diamantes Rey de Diamantes As de Corazones 2 de Corazones 3 de Corazones 4 de Corazones 5 de Corazones 6 de Corazones 7 de Corazones 8 de Corazones 9 de Corazones 10 de Corazones Sota de Corazones Reina de Corazones Rey de Corazones As de Picas 2 de Picas 3 de Picas 4 de Picas 5 de Picas 6 de Picas 7 de Picas 8 de Picas 9 de Picas 10 de Picas Sota de Picas Reina de Picas Rey de Picas
问题原因与解决方案
核心问题
Carta类的__eq__方法实现错误:Python中__eq__必须返回布尔值True或False,但你的代码返回1或-1。当列表执行in判断和remove操作时,非零数值都会被视为True,导致第一个元素就被判定为匹配目标,从而被误删。此外,当前__eq__只比较了牌的点数(valor),没有比较花色(palo),逻辑本身就不正确。Mazo类的__contains__方法笔误:方法中写的是return item in self.items,但Mazo类根本没有self.items属性,正确应该是self.cartas。不过这个笔误没影响到eliminaCarta的判断,因为函数里直接用了carta in self.cartas,但这个方法本身需要修正。
修正代码
1. 修正Carta类的__eq__方法
def __eq__(self, other): # 只有花色和点数都相同时,两张牌才相等 return self.palo == other.palo and self.valor == other.valor
2. 修正Mazo类的__contains__方法
def __contains__(self, item): return item in self.cartas
3. (可选但建议)修正比较运算符__lt__和__gt__
Python3中比较运算符应该返回布尔值,而非1或-1,虽然这不是当前问题的直接原因,但为了代码规范和兼容性,建议修正:
def __lt__(self, other): # 先比较花色 if self.palo != other.palo: return self.palo < other.palo # 花色相同,A的优先级最高(A比其他牌大) if self.valor == 1: return False # A不小于任何非A牌 if other.valor == 1: return True # 非A牌小于A # 其他情况比较点数 return self.valor < other.valor def __gt__(self, other): if self.palo != other.palo: return self.palo > other.palo if self.valor == 1: return True if other.valor == 1: return False return self.valor > other.valor
验证效果
修正后运行测试代码,Carta(1,13)(方块K)会被正确从牌堆中移除,不会再误删黑桃A。
内容的提问来源于stack exchange,提问作者Matias Alvarez

