类型对象 x 没有属性 y

2024-09-26 22:54:09 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试创建一个程序来随机处理两张牌。但是,它总是出现错误:

AttributeError: type object `CardPack` has no attribute `suits`

我不确定,但我认为这意味着类CardPack没有值suits。但是,在__init__函数中,它是被定义的。我完全被难住了。在

类别代码:

^{pr2}$

运行的文件创建实例:

#DEALING TEST
from DeckDealer import CardPack

Dealer = CardPack

cards = Dealer.deal(CardPack)

print("Your cards are %s and %s!" % (cards[1], cards[2]))

Tags: 函数no程序objectinittype错误attribute
2条回答

您没有在此处创建实例

Dealer = CardPack

这只是对类的另一个引用(a类型),因此__init__方法也不会被调用。在

调用类以生成实例:

^{pr2}$
Dealer = CardPack

此行不创建CardPack类型的实例,它只是复制对它的引用。因此,当您调用Dealer.deal()时,实际上是在执行CardPack.deal(),它无权访问实例属性。在

相反,您应该创建一个实例,然后对该实例调用方法:

^{pr2}$

在这种情况下,还需要注意的是,要调用一个方法,不是self传递一个值。当您在实例上调用方法时,self是隐式设置的。因此,当您执行dealer.deal()操作时,self会自动设置为dealer实例。如果您要调用dealer.deal(dealer),您将传递一个该方法没有的第二个参数,因此您将得到一个错误。这也是您在deal中的getRandomCards调用的问题:self.getRandomCards(self)self设置为第二个参数,给您一个错误。做self.getRandomCards()就是你想做的。在

尽管如此,请注意您的deal方法将有一个无限循环,因为只要cards不是3就继续迭代,但是您永远不会更改cards的值。所以您可能想增加循环中的值。但即使这样,访问空列表上的cardsDealt[cards]也会导致索引错误,所以您也需要修复它。您可以先重置列表,然后再向其添加append张新卡片,但更好的方法是一次只创建一个新列表,其中包含3张卡片。您可以使用列表理解来简化:

def deal(self):
    self.cardsDealt = [self.getRandomCards() for card in range(3)]
    return self.cardsDealt

最后,您的getRandomCards可能并没有完全按照您的预期操作。通常,你会期望每张牌都有相同的机会。然而,你要做到的是俱乐部卡有1/4的几率,黑桃卡有3/16的几率,红桃卡有9/64的几率,钻石卡有27/256的几率。这样就有81/256的几率获得无牌。这显然是不对的。在

发生这种情况的原因是你对每个测试都做了随机选择。所以为了测试你是否得到俱乐部卡,你要做一个选择(1/4的机会)。如果你没有得到一张黑桃牌(3/4的机会),你会做出另一个选择来获得黑桃牌(1/4的机会;所以总共是3/4*1/4)等等。相反,你应该只做一次选择,然后将结果重新用于子类别:

def getRandomCards(self):
    # only make *one* random choice for the suit
    suit = random.choice(self.suits)

    if suit == "C":
        return random.choice(self.cardsClubs)
    elif suit == "S":
        return random.choice(self.cardsSpades)
    elif suit == "H":
        return random.choice(self.cardsHearts)
    elif suit == "D":
        return random.choice(self.cardsDiamonds)

这也使得你不可能不从这个方法中随机得到一张牌,因为你总是得到四套西装中的一套。在


最后2点,正如gboffi在评论中提到的,你没有任何保护措施来阻止你得到多张相同的卡。从getRandomCards()得到三张同一张牌是可能的(不太可能,但仍然有可能),这在大多数游戏中是不可能的。在

为了防止这种情况,您可以在所有卡片的列表中使用^{}。这将给你三张(或任何数字)绝对不同的卡片。它还允许你有一个真正的“牌堆”,你从中抽牌,然后离开牌堆,直到你重新开始游戏。在

通过设置,您可以制作如下新牌组:

self.deck = self.cardsClubs + self.cardsSpades + self.cardsHearts + self.cardsDiamonds

这实际上只是将所有四个卡片列表组合在一起,创建一个新的卡片列表,然后可以从中提取。要从它们中提取三个,可以使用random.sample,如下所示:

drawnCards = random.sample(self.deck, 3)

然后你可以从牌堆中取出这些牌:

for card in drawnCards:
    self.deck.remove(card)

另一种方法是更接近真实的方式。你可以先洗牌,然后从最上面抽牌,而不是从牌堆中随机抽牌。要洗牌列表,可以使用^{},要从列表中提取和移除卡片,可以使用list.pop

# create the deck
self.deck = self.cardsClubs + self.cardsSpades + self.cardsHearts + self.cardsDiamonds

# shuffle the deck
random.shuffle(self.deck)

# and then draw three cards from it
drawnCards = [self.deck.pop() for i in range(3)]

相关问题 更多 >

    热门问题