类方法中的remove函数有问题

编程语言 2026-07-10

这是我在这个网站上的第一个问题。

问题是,我试图把一个Python 2的函数适配到Python 3.14,函数名为eliminaCarta,它接收一个名为carta的类,并从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

carta = Carta(1,1)

mazo = Mazo()

print(mazo)

打印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

但是,当调用mazo.eliminaCarta(carta)

carta = Carta(1,13)

mazo = Mazo()

mazo.eliminaCarta(carta)

print(mazo)

时,结果是:

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

第一个元素被删除,而应该删除的元素是 "Rey de Diamantes"

解决方案

.remove() 使用 Carta.__eq__ 来检查要删除哪张牌,并且有两个问题

  • 它还需要比较 self.palo == other.palo
  • bool(1) 给出 True,而 bool(-1) 也给出 True
    bool(0) 给出 False。但最好使用 True/False 代替 1/-1/0
    def __eq__(self, other):
        if (self.valor == other.valor) and (self.palo == other.palo): 
            return True
        else: 
            return False

但你可以写得更短一些(因为 ==and 已经给出 True/False

    def __eq__(self, other):
        return (self.valor == other.valor) and (self.palo == other.palo)

(正如 @MarcePuente在评论中提到的,你可以在没有括号的情况下写。我用它来让可读性稍微好一些。有时它更清楚地展示哪些元素是先被计算的)

现在 self.cartas.remove(carta) 可以正确工作。


顺便说一句:

在其他函数中,你也应该使用 True/False 代替 1/-1

正如 @JonSG指出,__contains__ 存在错误——应该是 self.cartas 而不是 self.items

@JonSG还指出 __lt__()__gt__() 应该把 >< 交换,但你在两处的代码完全一样。

我也不清楚为什么 __lt__()__gt__() 会同时有 if self.valor == 1 ...if other.valor == 1

关于 mezclar 的简短版本

    def mezclar(self):
        random.shuffle(self.cards)

在其他修改后的版本:

import random


class Card:
    # fmt: off
    all_colors = ["Clubs", "Diamonds", "Hearts", "Spades"]
    all_values = ["nothing", "Ace", "2", "3", "4", "5", "6", "7", "8", "9", "10", "Jack", "Queen", "King"]
    # fmt: on

    def __init__(self, color=0, value=0):
        self.color = color
        self.value = value

    def __str__(self):
        return self.all_values[self.value] + " of " + self.all_colors[self.color]

    def __lt__(self, other):
        if self.color > other.color:
            return True
        if self.color < other.color:
            return False

        # the same color
        return self.value < other.value

    def __gt__(self, other):
        if self.color < other.color:
            return True
        if self.color > other.color:
            return False

        # the same color
        return self.value > other.value

    def __eq__(self, other):
        return (self.value == other.value) and (self.color == other.color)

    def __le__(self, other):
        return (self < other) or (self == other)

    def __ge__(self, other):
        return (self > other) or (self == other)


class Deck:
    def __init__(self):
        self.cards = []
        for color in range(4):
            for value in range(1, 14):
                self.cards.append(Card(color, value))

    def display(self):
        # for card in self.cards:
        #    print(card)
        print(self)

    def __str__(self):
        s = ""
        for card in self.cards:
            s += f"{card}\n"
        return s

    def shuffle(self):
        random.shuffle(self.cards)

    def __contains__(self, item):
        return item in self.cards

    def remove(self, card):
        if card in self.cards:
            self.cards.remove(card)


# --- main ---

deck = Deck()
# print(deck)

card1 = Card(1, 13)
print(f"card1: '{card1}'")

print(f"deck contains '{card1}':", card1 in deck)
print(f"removing ... '{card1}'")
deck.remove(card1)
print(f"deck contains '{card1}':", card1 in deck)
# print(deck)

# deck.shuffle()
# print(deck)

print(f"'{card1}' and '{card1}'")
print("== :", card1 == card1)
print(">  :", card1 > card1)
print("<  :", card1 < card1)
print(">= :", card1 >= card1)
print("<= :", card1 <= card1)

card2 = Card(3, 10)
print(f"card2: '{card2}'")

print(f"'{card1}' and '{card2}'")
print("== :", card1 == card2)
print(">  :", card1 > card2)
print("<  :", card1 < card2)
print(">= :", card1 >= card2)
print("<= :", card1 <= card2)

# deck.display()
card1: 'King of Diamonds'
deck contains 'King of Diamonds': True
removing ... 'King of Diamonds'
deck contains 'King of Diamonds': False
'King of Diamonds' and 'King of Diamonds'
== : True
>  : False
<  : False
>= : True
<= : True
card2: '10 of Spades'
'King of Diamonds' and '10 of Spades'
== : False
>  : True
<  : False
>= : True
<= : False
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章