如何从 python 集中删除自定义对象的实例?

kro*_*ike 3 python set python-3.x

我正在用 python 进行一些基本的卡/牌组操作。下面你可以看到我的 Card 类和 Deck 类。假设我知道有些牌已经死了,并且想将它们从牌组中删除。

import itertools

SUIT_LIST = ("h", "s", "d", "c")
NUMERAL_LIST = ("2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A")

class Card:
    def __init__(self, numeral, suit):
        self.numeral = numeral
        self.suit = suit
        self.card = self.numeral, self.suit
    def __repr__(self):
        return self.numeral + self.suit

class Deck(set):
    def __init__(self):
        for numeral, suit in itertools.product(NUMERAL_LIST, SUIT_LIST):
            self.add(Card(numeral, suit))

deck = Deck()    
dead_card = Card('J','s')
deck.remove(dead_card)
Run Code Online (Sandbox Code Playgroud)

引发以下错误:

Traceback (most recent call last):

  File "<ipython-input-93-06af62ea1273>", line 23, in <module>
    deck.remove(dead_card)

KeyError: Js
Run Code Online (Sandbox Code Playgroud)

从我的套牌中移除死牌的正确方法是什么?为什么我的方法不起作用?

wim*_*wim 5

您的班级需要两个新方法Card,以便集合和字典中的成员资格能够正常工作:

class Card:
    ...
    def __hash__(self):
        return hash(self.card)
    def __eq__(self, other):
        if isinstance(other, Card):
            return self.card == other.card
        return NotImplemented
Run Code Online (Sandbox Code Playgroud)

这是因为集合是使用哈希表实现的,除非您定义如何哈希和比较自定义类的实例,否则基于身份(CPython 中的内存位置)的哈希将用作默认值。使用id在这里提供了一个相当蹩脚的默认值 - 两张具有相同数字/花色的牌不会被视为“相等”,并且 a 中的成员资格Deck不会被识别。