表示子类就像具有一个对象的超类的结构的最佳方法

Best way to represent structure where subclass is like a superclass with one object

我想表示一种类似于无序纸牌的结构(例如,在 Python 3.7 中),它具有 属性 可以将单张纸牌视为一副牌。

class Deck:
    def __init__(self, cards, owner):
        self.owner = owner
        self.cards = cards


class Card(Deck):
    def __init__(self, number, suit, owner):
        self.number = number
        self.suit = suit
        super().__init__({self}, owner)

    def __eq__(self, other):
        return self.number == other.number and self.suit == other.suit and self.owner == other.owner

    def __hash__(self):
        return hash((self.number, self.suit, self.owner))


card = Card(5, 'clubs', 'me')

(上面的returnsAttributeError: 'Card' object has no attribute 'owner')

如果我想订购我的牌组,这很简单,因为 Card.__init__() 只会将列表 [self] 传递给 Deck.__init__()。但是,我不能只将 {self} 传递给 Deck.__init__(),因为 Card.__hash__() 可能需要已经设置 Deck 属性!有很多解决方法;我可以简单地在 Card.__init__() 中设置 self.owner = owner,或者我可以将 [self] 传递给 Deck.__init__(),然后在正文中设置 self.cards = set(cards),但我觉得这很奇怪代码的其他部分应取决于牌组选择如何存储其卡片。因此,我的问题不是如何编码这个,而是设计这种关系的最佳方式,这样我就没有去担心这些问题。有什么想法吗?

我搜索了这个问题,但没有找到任何内容,但它很简单,如果重复,我深表歉意。感谢阅读!

编辑:如果一副纸牌对我的结构来说是一个糟糕的类比,那么(希望)更准确的类比是多项式,它是单项式的总和,但每个单项式也是一个多项式,它本身就是一个学期。

我认为这里的问题是您的想法 "a single card can be thought of as a deck of size one." 不太连贯,您偶然发现了一个非常具体的原因说明。

一副牌与单张牌是根本不同的概念,为了让一副牌存在,非一副牌也必须独立存在。

您可以通过思考操作 "adding one card" 来了解这一点 — 您应该能够对牌组执行此操作,并且应该会产生一副由两张牌组成的牌组。但是你不应该对一张牌这样做,因为这样一来,已经包含该牌的其他一些牌组会突然变成混合类型——它会有一些牌是一张牌,一些是两张牌,这不是一副牌的工作方式(并且会破坏迭代等)。

所以我认为这里的正确选择是在需要时简单地支持将牌组分成更小的牌组 — 可以将一张牌从牌组中移出建模为 "splitting the deck into two decks, one of N-1 cards and one of 1 card",但是 1 张牌的牌组仍然需要在其中包含一个非甲板卡片对象,否则你会遇到问题。

我将忽略此设计的问题并关注所提供代码中的错误。

AttributeError 是由 {self} 引起的:

super().__init__({self}, owner)

这会尝试在完全初始化之前获取 self 的哈希值。

{self} 替换为 [self],您的代码可以正常运行。