黑桃 A 的奇特案例(在 python3 中创建对象数组)

The curious case of the Ace of Spades (creating array of objects in python3)

我正在尝试创建一个对象(卡片)数组(卡片组)。为此,我在 Deck.construct() 方法内的 Deck.card 对象上使用 Card.construct() 方法。我能够成功地创建一个卡片对象数组 (Deck.cards),问题是所有这些都是黑桃 A,其中 52 个。这是创建数组的地方:

def construct(self):
        for value in self.card.values:
            for suit in self.card.suits:
                self.card.construct(value, suit)
                self.card.showNice()
                self.cards.append(self.card)

在分配之前正确打印了不同种类的纸牌,但由于某种原因,似乎只有黑桃 A 被附加到数组中。我真的不明白为什么会这样。

import random

class Card:
    def __init__(self):
        self.value = ''
        self.values = ['2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K', 'A']
        self.suit = ''
        self.suits = ['♥', '♦', '♣', '♠']
        self.valit = (self.value, self.suit)

    def construct(self, value, suit):
        self.value = value
        self.suit = suit
        self.valit = (value, suit)

    def random(self):
        self.valit = (random.choice(self.values), random.choice(self.suits))

    def show(self):
        print(self.valit, end='')

    def showNice(self):
        print(self.value, self.suit, ' ', sep='', end='')

class Deck:
    def __init__(self):
        self.card = Card()
        self.cards = []

    def construct(self):
        for value in self.card.values:
            for suit in self.card.suits:
                self.card.construct(value, suit)
                self.cards.append(self.card)

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

    def show(self):
        for card in self.cards:
            card.show()
        print('\n')

    def showNice(self):
        for card in self.cards:
            card.showNice()
        print('\n')

...

#!/usr/bin/python
from environment.environment import *

class shuffleUpAndDeal():
    deck = Deck()
    deck.construct()
    deck.shuffleUp()
    deck.showNice()

if __name__ == '__main__':
    shuffleUpAndDeal()

我对对象、类、方法等的整个概念都不熟悉,所以很可能我没有以正确的方式优化代码,非常感谢任何建议。提前致谢!

问题是,您一遍又一遍地重复使用 Card 的同一个实例,并在将其添加到列表后对其进行更改。您已将对同一张卡片的引用添加到列表中 52 次,并更改同一张卡片 52 次。这就是为什么它最终出现在最后一个组合上的原因。

注意这部分:

def construct(self):
    for value in self.card.values:
        for suit in self.card.suits:
            self.card.construct(value, suit)
            self.cards.append(self.card)

    print(self.cards) # I added this line

这是 print 打印的内容:

[<__main__.Card object at 0x0377DB10>, <__main__.Card object at 0x0377DB10>, <__main__.Card object at 0x0377DB10>, <__main__.Card object at 0x0377DB10>, <__main__.Card object at 0x0377DB10>, <__main__.Card object at 0x0377DB10>, <__main__.Card object at 0x0377DB10>, <__main__.Card object at 0x0377DB10>, <__main__.Card object at 0x0377DB10>, <__main__.Card object at 0x0377DB10>, <__main__.Card object at 0x0377DB10>, <__main__.Card object at 0x0377DB10>, <__main__.Card object at 0x0377DB10>, <__main__.Card object at 0x0377DB10>, <__main__.Card object at 0x0377DB10>, <__main__.Card object at 0x0377DB10>, <__main__.Card object at 0x0377DB10>, <__main__.Card object at 0x0377DB10>, <__main__.Card object at 0x0377DB10>, <__main__.Card object at 0x0377DB10>, <__main__.Card object at 0x0377DB10>, <__main__.Card object at 0x0377DB10>, <__main__.Card object at 0x0377DB10>, <__main__.Card object at 0x0377DB10>, <__main__.Card object at 0x0377DB10>, <__main__.Card object at 0x0377DB10>, <__main__.Card object at 0x0377DB10>, <__main__.Card object at 0x0377DB10>, <__main__.Card object at 0x0377DB10>, <__main__.Card object at 0x0377DB10>, <__main__.Card object at 0x0377DB10>, <__main__.Card object at 0x0377DB10>, <__main__.Card object at 0x0377DB10>, <__main__.Card object at 0x0377DB10>, <__main__.Card object at 0x0377DB10>, <__main__.Card object at 0x0377DB10>, <__main__.Card object at 0x0377DB10>, <__main__.Card object at 0x0377DB10>, <__main__.Card object at 0x0377DB10>, <__main__.Card object at 0x0377DB10>, <__main__.Card object at 0x0377DB10>, <__main__.Card object at 0x0377DB10>, <__main__.Card object at 0x0377DB10>, <__main__.Card object at 0x0377DB10>, <__main__.Card object at 0x0377DB10>, <__main__.Card object at 0x0377DB10>, <__main__.Card object at 0x0377DB10>, <__main__.Card object at 0x0377DB10>, <__main__.Card object at 0x0377DB10>, <__main__.Card object at 0x0377DB10>, <__main__.Card object at 0x0377DB10>, <__main__.Card object at 0x0377DB10>]

看到 0x0377DB10 位了吗?那是对象的地址。请注意它们是如何完全相同的!每次调用 self.card.construct(value, suit) 时,您只是在更改该单个实例,包括已经在 self.cards.

中的所有对它的引用

If you 运行 your test, then 改成 deck.card.suit, then 运行 the再次测试,你会发现所有的卡片都同时发生了变化。

每次都创建一张新卡,这样您就不会经常覆盖同一个实例。

这是一个可以使用的修改版本。请注意我每次都是如何创建新卡片的:

def construct(self):
    for value in self.card.values:
        for suit in self.card.suits:
            card = Card()
            card.construct(value, suit)

            self.cards.append(card)

    print(self.cards)

这是新版本打印的内容:

[<__main__.Card object at 0x0376DB90>, <__main__.Card object at 0x0376DBB0>, <__main__.Card object at 0x0376DBD0>, <__main__.Card object at 0x0376DBF0>, <__main__.Card object at 0x0376DC10>, <__main__.Card object at 0x0376DC30>, <__main__.Card object at 0x0376DC50>, <__main__.Card object at 0x0376DC70>, <__main__.Card object at 0x0376DC90>, <__main__.Card object at 0x0376DCB0>, <__main__.Card object at 0x0376DCD0>, <__main__.Card object at 0x0376DCF0>, <__main__.Card object at 0x0376DD10>, <__main__.Card object at 0x0376DD30>, <__main__.Card object at 0x0376DD50>, <__main__.Card object at 0x0376DD70>, <__main__.Card object at 0x0376DD90>, <__main__.Card object at 0x0376DDB0>, <__main__.Card object at 0x0376DDD0>, <__main__.Card object at 0x0376DDF0>, <__main__.Card object at 0x0376DE10>, <__main__.Card object at 0x0376DE30>, <__main__.Card object at 0x0376DE50>, <__main__.Card object at 0x0376DE70>, <__main__.Card object at 0x0376DE90>, <__main__.Card object at 0x0376DEB0>, <__main__.Card object at 0x0376DED0>, <__main__.Card object at 0x0376DEF0>, <__main__.Card object at 0x0376DF10>, <__main__.Card object at 0x0376DF30>, <__main__.Card object at 0x0376DF50>, <__main__.Card object at 0x0376DF70>, <__main__.Card object at 0x0376DF90>, <__main__.Card object at 0x0376DFB0>, <__main__.Card object at 0x0376DFD0>, <__main__.Card object at 0x0376DFF0>, <__main__.Card object at 0x03775030>, <__main__.Card object at 0x03775050>, <__main__.Card object at 0x03775070>, <__main__.Card object at 0x03775090>, <__main__.Card object at 0x037750B0>, <__main__.Card object at 0x037750D0>, <__main__.Card object at 0x037750F0>, <__main__.Card object at 0x03775110>, <__main__.Card object at 0x03775130>, <__main__.Card object at 0x03775150>, <__main__.Card object at 0x03775170>, <__main__.Card object at 0x03775190>, <__main__.Card object at 0x037751B0>, <__main__.Card object at 0x037751D0>, <__main__.Card object at 0x037751F0>, <__main__.Card object at 0x03775210>]

请注意所有地址都不一样!他们现在都是不同的卡片了。

当我运行你的测试时,我得到:

2♥ K♥ 3♥ J♥ 6♥ 5♣ 7♣ 7♦ 8♣ 5♦ 3♣ Q♥ 10♣ 9♣ 9♥ A♦ 8♥ 9♠ 6♠ A♠ K♣ K♠ J♦ 2♦ 7♥ 10♠ 6♦ 6♣ 4♠ 5♠ K♦ 3♦ 4♥ 9♦ Q♠ 7♠ A♣ 4♣ 10♦ A♥ Q♦ 4♦ 5♥ J♣ 8♠ 3♠ J♠ Q♣ 8♦ 10♥ 2♣ 2♠

我想指出 construct 方法是不必要的。它正在做 Card 构造函数应该做的工作,但以一种不太直观的方式。构造函数的指向是construct。想一想如果您忘记调用 construct,卡片会变成什么样子。如果您只使用构造函数,就不可能忘记。