【问题标题】:How to remove instance of custom object from python set?如何从 python 集中删除自定义对象的实例?
【发布时间】:2019-01-07 23:48:57
【问题描述】:

我正在玩一些 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

从我的牌组中移除死牌的正确方法是什么?为什么我这样做的方式不起作用?

【问题讨论】:

  • 它不像你那样工作,因为你没有完成属于set的项目的实现。
  • 为什么不将卡片存储为字符串或元组?

标签: python python-3.x set


【解决方案1】:

您需要在 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 中的成员资格不被识别。

【讨论】:

  • 你不需要__ne__吗?
  • 不,我不相信你在这里。
  • @Jean-FrançoisFabre 底层算法使用__hash__ 来推断项目可能在哈希表中的位置。然后它使用__eq__ 来测试是否真的存在,或者只是另一个具有相同哈希的对象。没有使用其他特殊方法。
  • 相关:stackoverflow.com/questions/4169252/…。找不到合适的副本,很多问答都很相似,但完全不是这样。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-12
  • 1970-01-01
相关资源
最近更新 更多