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

时间:2018-07-31 14:28:11

标签: python python-3.x set

我正在用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)

引发以下错误:

Traceback (most recent call last):

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

KeyError: Js

从我的卡座上删除死卡的正确方法是什么?为什么我的方法不起作用?

1 个答案:

答案 0 :(得分:4)

您需要在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

这是因为集合是通过hash tables实现的,除非您定义如何哈希和比较自定义类的实例,否则将使用基于identity(在CPython中的内存位置)的哈希作为默认值。使用id在这里提供了一个非常糟糕的默认设置-两张相同编号/相同花色的卡将不被视为“相等”,并且Deck中的会员身份也无法识别。