Python中的二维列表问题

时间:2019-07-11 13:09:44

标签: python

昨天,我决定第一次开始使用Python,所以请放轻松,我几乎没有编程经验。 作为我的第一个小项目,我正在尝试制作一个脚本,对牌组进行洗牌,并从洗牌后发出5张牌。 我正在尝试将手存储在二维数组/矩阵中。 这是我遇到的代码:

var styleWithoutAttr = styleTags.replace("type=['\"]text/css['\"]", '')

我的import random sorted_deck = ["AH","KH","QH","JH","TH","9H","8H","7H","6H","5H","4H","3H","2H", "AS","KS","QS","JS","TS","9S","8S","7S","6S","5S","4S","3S","2S", "AD","KD","QD","JD","TD","9D","8D","7D","6D","5D","4D","3D","2D", "AC","KC","QC","JC","TC","9C","8C","7C","6C","5C","4C","3C","2C"] def shuffle(): sorted_deck_current = list() sorted_deck_current.clear() sorted_deck_current = sorted_deck.copy() shuffled_deck = list() shuffled_deck.clear() for n in range(0,52): r = random.randrange( 0, len(sorted_deck_current) ) shuffled_deck.append( sorted_deck_current[r] ) sorted_deck_current.pop( r ) return shuffled_deck for n in range(2): # Check that the shuffle()-function works fresh_shuffled = shuffle() print( "Shuffled deck: " + str(fresh_shuffled) ) many_hands = list() temp_hand = list() temp_deck = list() many_hands.clear() for n in range(5): # Draw 5 hands from freshly shuffled decks temp_hand.clear() temp_deck.clear() temp_deck = shuffle() for i in range(5): temp_hand.append( temp_deck[i] ) many_hands.append( temp_hand ) print( many_hands[n] ) for q in range(5): # Try and output the 5 different hands again print( many_hands[q] ) exit() 循环在代码末尾输出5张不同的牌,这就是我想要的。 for n in range(5)循环输出同一手牌5次,恰好是前一个循环的最后一手牌。 我不知道为什么会这样。 如果有人可以向我解释这种行为,将不胜感激。

3 个答案:

答案 0 :(得分:2)

您正在创建temp_hand,然后再开始第一个for循环。之后,您总是总是修改同一对象,然后将其重新添加到many_hands。本质上,您只是将同一对象添加了五次。如果您熟悉C,那就像传递引用:python在追加列表之前不复制列表的值,它只是将引用添加到列表。

因此,稍后,当您尝试打印many_hands时,它将打印同一对象5次。

此问题的解决方案是在temp_hand循环内而不是外部初始化for 内部,以便每次迭代都将其初始化(作为新参考) 。也就是说,替换行

temp_hand.clear()

使用

修改您当前拥有的单个列表,而不更改其引用
temp_hand = list()

,它将在新引用处创建一个新的空列表,并将其分配给temp_hand


顺便说一句,初始化空列表时,通常首选使用列表文字(即[])而不是list()构造函数。这主要是因为它从其周围的代码中脱颖而出,它肯定是一个列表,而不是恰好返回一个列表的函数调用。

答案 1 :(得分:1)

首先修复,在每次迭代时创建一个新的列表对象:

for draw in range(5): # try avoid single letter variables
    temp_hand = [] # Make a NEW list object. BTW, [] is nicer and more common syntax than list()
    temp_deck = shuffle()
    temp_hand = temp_deck[:5] # Use slicing to get the first 5 elements, not a loop!
    many_hands.append(temp_hand) # This will get a different list object appended each time which is what you want.

那出了什么问题?在python中,当您将列表分配给变量时,您不会分配列表的副本,而是对其的引用。尝试以下代码:

list1 = [1, 2, 3] # Make a new list object
list2 = list1 # Assigns a reference to the existing list1
list1[0] = 9
print(list2)

您将看到list2已更改。这是因为list1list2指向同一个对象。您可以使用isid在python中进行检查:

print(f"list1 id: {id(list1)}")
print(f"list2 id: {id(list2)}")

它们是相同的。另外,list1 is list2返回True

但是现在尝试一下:

list1 = [1, 2, 3]
list2 = [1, 2, 3]

现在list1 == list2True,但是list1 is list2False。它们是单独的对象。

list1 = [1, 2, 3]
list2 = [1, 2, 3]
list1[0] = 9
print(list2)

这次list2尚未更改。

在原始代码中,您通过调用temp_hand来保持对.append()的引用,而不是在每次迭代中创建一个新的列表对象。因此,在每个循环中,您都洗牌temp_hand并打印,然后看到新手。但是,您未查看的是many_hands中已经发生的值发生了什么。这些都指向同一个对象,因此它们 all 都在每次迭代中进行更改。

这是证明这一点的另一种方式:

list1 = []
for _ in range(5):
    list1.clear()
    list1.append(1) # It is really your use of append that is the culprit as this is where you EDIT an existing list instead of ASSIGNING a new one
    list2 = [1]
    print(f"list1 id: {id(list1)}, list2 id: {id(list2)}")

看看list1总是一样,但是list2每次都改变吗?


一开始我的代码可以更短,但是我想说明使用[]创建列表,但是实际上shuffle本身会创建一个新列表,因此您可以这样做:

for draw in range(5): # try avoid single letter variables
    temp_hand = shuffle()[:5] 
    many_hands.append(temp_hand)

答案 2 :(得分:0)

您无需为每只手创建新列表,而是为每只手清空并填充temp_hand,这样many_hands便是该同一列表/手的5个引用的列表。

如果您执行temp_hand.clear()而不是temp_hand = list()(将其设为新的空白列表),则应该获得期望的结果。