在python中,当我只更改列表中的一行时,为什么所有行都会更改?

2024-09-19 23:33:24 发布

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

我写了一个搜索宝藏的代码。正如代码所示,当我放下声纳时,它会显示胸部的提示。但是,在我的代码中,所有行都将更改。我真的不知道为什么。我希望有人能帮我。非常感谢!你知道吗

import random,math

class OcenTreasure:
    def __init__(self):
        self.board=[]
        self.chests=[]
        self.treasure=3
        self.sonar=20
        self.drop=[]

    def get_board(self):
        colume=['~']*60
        for y in range(0,15):
            self.board.append(colume)
        return self.board

    def drawBoard(self):
        row=0
        print('             1         2         3         4         5 ',\
              '   012345678901234567890123456789012345678901234567890123456789',\
              sep='\n')
        while row<15:
            if row<10:
                line=''.join(self.board[row])
                print(' '+str(row),line,str(row))
            if row>=10:
                line=''.join(self.board[row])        
                print(str(row),line,str(row))
            row+=1
        print('             1         2         3         4         5 ',\
              '   012345678901234567890123456789012345678901234567890123456789',\
              sep='\n')  

    def getChests(self):
        cont=True
        while cont==True:
            for i in range(0,3):
                a=random.randint(0,14)
                b=random.randint(0,59)
                aList=[b,a]
                if aList in self.chests:
                    aList=[]
                else:
                    self.chests.append(aList)
                    cont=False

        return self.chests


    def dropSonar(self,choice):
        if choice in self.drop:
            self.sonar-=1
            return (print('You already dropped a sonar there. You lost another sonar device'))
        else:
            self.drop.append(choice)
        pos=choice.split()
        x=int(pos[0])
        y=int(pos[1])
        for item in self.chests:
            xgap=math.fabs(x-item[0])
            ygap=math.fabs(y-item[1])
            if ygap>5 and xgap>9:
                self.board[y][x]='O'
            else:
                if xgap==0 and ygap==0:
                    self.board[y][x]='X'
                    self.chests.remove(item)
                    self.treasure-=1
                if xgap<2*ygap:
                    self.board[y][x]=str(int(xgap))
                if xgap>=2*ygap:
                    if ygap==1:
                        self.board[y][x]='a'
                    if ygap==2:
                        self.board[y][x]='b'
                    if ygap==3:
                        self.board[y][x]='c'
                    if ygap==4:
                        self.board[y][x]='d'                    
                    if ygap==5:
                        self.board[y][x]='e'
        self.sonar-=1

gameOver=False 
t=OcenTreasure()
t.get_board()
a=t.getChests()
print(a)
while gameOver==False:
    t.drawBoard()    
    print(t.board)
    print('Where do you want to drop your sonar?')
    if t.sonar>0:
        choice=input('Enter coordinates x y (x in [0..59] and y in [0..14]) (or Q to quit and H for help): ').lower()
        if choice=='q':
            print('The chests were in: '+str(t.chests))
            print('Thank you for playing Ocean Treasures')
            gameOver=True
        else:
            t.dropSonar(choice)
            if t.treasure==0:
                print('Well done! You found all the 3 treasure Chests using '+\
                      str(t.sonar)+' out of 20 sonar devices.')
                gameOver=True
            else:
                print('You have '+str(t.sonar)+\
                      ' sonar devices available. Treasures found: '\
                      +str(3-t.treasure)+'. Still to be found: '+\
                      str(t.treasure)+'.')
    else:
        print('You lost all your 20 sonar devises.')
        print('The remaining chests were in: '+str(t.chests))
        gameOver=True

Tags: inselfboardifdefelserowprint
2条回答

get_board函数中,您正在创建colume,然后一次又一次地将它附加到board中—但这并不是每次都创建一个新列表,而是同一个对象。你知道吗

def get_board(self):
    colume=['~']*60
    for y in range(0,15):
        self.board.append(colume)
    return self.board

每次此函数执行self.board.append(colume)时,它都不会执行“将'colume'的内容添加到'自板,而是说“添加另一个对‘colume’的引用”自板,这样self.board中的每个条目都是相同的对象。您可以使用id来测试它,以获得对象的内部标识符。每个人都应该有所不同。当我尝试时:

>>> board = list()
>>> colume=['~']*60
>>> for y in range(0,15):
...     self.board.append(colume)
>>> id(board[0])
140498301136840
>>> id(board[1])
140498301136840
>>> id(board[2])
140498301136840

相反,如果您这样做:

>>> board = list()
>>> for y in range(0,15):
...     board.append(['~'] * 60)
>>> id(board[0])
140498301203376
>>> id(board[1])
140498301176432
>>> id(board[2])
140498301204456

所有不同的对象,更改其中一个不会更改板的其他“行”。你知道吗

在python中,列表是可变的。另外,当您在另一个列表中插入一个列表时,存储的是引用。你知道吗

看看如果运行此代码会发生什么(我使用了与getChest方法相同的变量名)

aList = [1,2,3]
chests=[]
chests.append(aList)
chests.append(aList)

print chests
aList[0] = 999
print chests

您可以在任何python书籍中搜索“reference”和“mutable”这两个术语,以获得更全面的解释。还可以查看copy模块(查找“深度复制”和“浅层复制”概念)。你知道吗

相关问题 更多 >