Skip to main content
 首页 » 编程设计

python之为什么我不能从字典中追加这个值

2025年05月04日15yjmyzz

我有一个旨在模拟纸牌游戏 21 的程序。以下是我的代码中的重要元素,这些元素非常 self 解释(我已经突出显示了我稍后会提到的行)

spades = ['2S','3S','4S','5S','6S','7S','8S','9S','10S','JS','QS','KS','AS'] 
hearts = ['2H','3H','4H','5H','6H','7H','8H','9H','10H','JH','QH','KH','AH'] 
clubs = ['2C','3C','4C','5C','6C','7C','8C','9C','10C','JC','QC','KC','AC'] 
diamonds = ['2D','3D','4D','5D','6D','7D','8D','9D','10D','JD','QD','KD','AD'] 
allCards = spades + hearts + clubs + diamonds 
 
cardVal = {'2S':2,'3S':3,'4S':4,'5S': 5,'6S':6,'7S':7,'8S':8,'9S':9,'10S':10,'JS':10,'QS':10,'KS':10,'AS':11, 
    '2H':2,'3H':3,'4H':4,'5H':5,'6H':6,'7H':7,'8H':8,'9H':9,'10H':10,'JH':10,'QH':10,'KH':10,'AH':11, 
    '2C':2,'3C':3,'4C':4,'5C':5,'6C':6,'7C':7,'8C':8,'9C':9,'10C':10,'JC':10,'QC':10,'KC':10,'AC':11, 
    '2D':2,'3D':3,'4D':4,'5D':5,'6D':6,'7D':7,'8D':8,'9D':9,'10D':10,'JD':10,'QD':10,'KD':10,'AD':11} 
 
import random 
random.shuffle(allCards) 
 
playerCards = [allCards.pop() for i in range(2)] 
dealerCards = [allCards.pop() for i in range(2)] 
playerHand = [] 
dealerHand = [] 
playerHandVal = 0 
dealerHandVal = 0 
 
def handVal(playercards,playerhand,score): 
    playerhand = [] 
    for i in playercards: 
        playerhand.append(cardVal[i]) ####### LINE 29 ###### 
    score = sum(playerhand) 
    print(score) 
 
handVal(playerCards,playerHand,playerHandVal) 
handVal(dealerCards,dealerHand,dealerHandVal) 
 
def twist(playercards,playerhand,score): 
    newCard = [allCards.pop() for i in range(1)] 
    playercards.append(newCard) 
    handVal(playercards,playerhand,score)    ####### LINE 39 ######## 
 
move = input('Stick (S) or Twist (T) : ') 
 
if move == 'T' or move == 't': 
    while move == 'T' or 't': 
        twist(playerCards,playerHand,playerHandVal)  ######## LINE 45 ######## 
        print(playerHand) 
        if playerHandVal > 21: 
            move = 's' 
            break 
        move = input('Stick (S) or Twist (T) : ') 

当我运行脚本时,它将生成两个长度为 2 的数组,并在输入提示 Stick (S) or Twist (T) : 之前为这些牌给出正确的牌值。但是,选择扭曲时,程序会产生此错误,

  line 45, in <module> 
    twist(playerCards,playerHand,playerHandVal) 
  line 39, in twist 
    handVal(playercards,playerhand,score) 
  line 29, in handVal 
    playerhand.append(cardVal[i]) 
TypeError: unhashable type: 'list' 

我的问题是,为什么这部分代码 playerhand.append(cardVal[i]) 最初有效,但在 twist 函数中调用时却无效

请您参考如下方法:

当你这样做时:

newCard = [allCards.pop() for i in range(1)] 
playercards.append(newCard) 

您正在将 list 插入到 playercards 中,其中包含从 allCards 中弹出的单个值,而不是值本身。

稍后,当您这样做时:

for i in playercards: 
    playerhand.append(cardVal[i]) ####### LINE 29 ###### 

i 不是索引,也不是键本身,它是一个元素 list ,其中包含我认为是您想要的键; list 是可变的,因此不适合作为 dict 的键,cardVal 是一个 dict。

它最初有效,因为您将 playerhand 初始化为包含两张牌的 list,而不是单元素 list 的 list 当您执行 playerCards = [allCards.pop() for i in range(2)] 时,是您实现不正确的额外抽奖。

修复方法是用卡片填充 playercards,而不是卡片的单元素 list:

newCard = allCards.pop() # Get the value, not a one-element `list` containing the value 
playercards.append(newCard) 

如果目标是弹出并附加几张卡片(并且您暂时只是使用 range(1) 作为占位符),则单独附加每张卡片,而不是附加 list 卡片作为单个元素,您可以执行以下任一操作:

newCard = [allCards.pop() for i in range(1)] 
playercards.extend(newCard)  # extend appends each element from the iterable 

或者由于 playercards 和 newCard 都是 list,您可以使用运算符重载:

newCard = [allCards.pop() for i in range(1)] 
playercards += newCard  # Same as extend, but only works when both sides are same type