为什么我不能在OO设置中迭代时删除列表元素?

时间:2012-04-09 19:41:05

标签: python class blackjack

我的情况如下:我正在开发BlackJack的实现。我有卡,手,球员,甲板和游戏课程。主要游戏对象存储玩家和牌组,而玩家存储存放牌的牌。

我经常做以下事情。在这个例子中,我正在向每个玩家发放初始牌。

num_cards = 2
for player in self.players:
    new_hand = Hand()
    for i in range(num_cards):
        new_hand.add_card(self.deck.get_next_card())
    player.assign_hand(new_hand)

这非常有效。我现在的问题是我希望从玩家的手牌中删除一手牌(玩家可以在BlackJack中分割,从而导致生成多手牌)。在下面的函数中,我打算遍历每个玩家的手。如果手的值大于21,我想删除手。 (请注意,下面的remove()函数通常在Player类中执行,通过名为fold_hand()的Player方法调用。我遇到了同样的问题,所以我已经将代码移到了更为明显的位置用于说明目的。)< / p>

for player in self.players:
    for hand in player.hands:
        if hand.smallest_value() > 21:
            player.hands.remove(hand)

这不起作用。为了清楚起见,我可以在remove()行之前打印出手,之后不会打印出来。也就是说,它似乎被删除了。然而,在下一轮比赛中,手又回来了。因此,球员的双手每一次都会成长。

上面的代码位于Game类中名为validate_player_hands()的函数中。此函数从名为play.py的文件中调用,该文件用于开始/结束游戏并促进主游戏循环。因此,对validate_player_hands()的唯一调用是在游戏循环中的play.py文件中,一个缩进。我打电话给:

game.validate_player_hands()

我也试过找到手的索引并使用'del'关键字,但结果是一样的。

为什么列表元素(名为player.hands的列表中的Hand对象)在看起来已被删除时无法删除?

提前致谢,

ParagonRG

4 个答案:

答案 0 :(得分:3)

如何使用简单的列表理解消除手:

for player in self.players:
    player.hands = [hand for hand in player.hands if hand.smallest_value() <= 21]

修改

使用过滤器:

for player in self.players:
    player.hands = filter(lambda x: x.smallest_value() <= 21, player.hands)

答案 1 :(得分:2)

创建一个副本并使用与对象长度相关的索引迭代该对象。使用0设置要删除的每个元素,然后过滤手以清除零。

for player in self.players:
    for hand_idx in range(len(player.hands)):
        if player.hands[hand_idx].smallest_value() > 21:
            player.hands[hand_idx]=0
    player.hands=filter(None,hands)

答案 2 :(得分:0)

您需要执行以下操作:

newList = hands[:]   
for hand in newList:  
    if hand.smallest_value() > 21:  #your code here
            player.hands.remove(hand)

这允许您在迭代该副本时制作要修改的列表的副本,从而避免Mihai提到的“树枝”场景。

答案 3 :(得分:0)

这可以通过在“for”语句的末尾添加[:]来解决。这将创建列表的副本。然后,您可以在更改原始列表时循环复制副本:

for player in self.players:
    for hand in player.hands[:]:
        if hand.smallest_value() > 21:
            player.hands.remove(hand)

(这是Python的list slicing语法。它是复制列表的fastest方法之一。更常见的是,这种语法以some_list[3:8]的形式用于从索引中获取列表条目3到7(包括3和7),但是通过省略第一个数字,您可以从列表的开头获取所有内容,并且通过省略最后一个数字,您可以获得列表末尾的所有内容。)