2016-03-21 50 views
1

我之前在玩一些代码,并且发现了一些相当奇怪的东西,我一直无法解释它。列表值改变应该保持不变的地方

以下是除了一件事以外完全相同的两个功能。变量origionalPos是第一个函数中的一个列表,第二个中是一个元组。

def ticking_as_list(): 
    tick = False 
    ticking = False 
    originalPos = [0,0] 
    pos = [0,0] 

    x = 0 
    RUNNING = True 
    while RUNNING: 
     x += 1 
     if x % 50 == 0: 
      tick = not tick 
      ticking = not ticking 

     if ticking: 
      originalPos = pos 
      ticking = False 

     pos[0] = originalPos[0] + 10 
     pos[1] = originalPos[1] + 10 

     if x == 500: 
      RUNNING = False 
      print(pos) 

def ticking_as_tuple(): 
    tick = False 
    ticking = False 
    originalPos = (0,0) 
    pos = [0,0] 

    x = 0 
    RUNNING = True 
    while RUNNING: 
     x += 1 
     if x % 50 == 0: 
      tick = not tick 
      ticking = not ticking 

     if ticking: 
      originalPos = (pos[0],pos[1]) 
      ticking = False 

     pos[0] = originalPos[0] + 10 
     pos[1] = originalPos[1] + 10 

     if x == 500: 
      RUNNING = False 
      print(pos) 

的功能设定更改数值的pos和50每次x整除加10给他们,并打印出结果时,它等于500有更容易的方式来做到这一点我知道,但这不是问题的主题。

当我运行这些功能中的任何一个时,我希望从它们两个都得到[110,110]的输出,但是;当我真正遇到他们时,输出如下:

>>> ticking_as_list() 
[4520,4520] 
>>> ticking_as_tuple() 
[110,110] 

ticking以列表的功能明显比当它是一个元组高得多。当我在每个函数执行时通过打印pos来查看每个函数执行的情况时,它会显示每次迭代时都会将10添加到pos,而只有在每次迭代后第50次时它才是元组。

为什么即使值ticking等于false,该列表也会始终更新?如图所示在代码:

 if x % 50 == 0: 
      tick = not tick 
      ticking = not ticking 

     if ticking: 
      originalPos = pos 
      ticking = False 

tickingx是由50只整除变为真,并立即变为假之后。但是,这应该使originalPos只在更新时才更新;它没有。它确实可以作为元组值正常工作。为什么是这样?如果我不小心改变了其他地方的值,那么在元组函数中会出现一个错误,因为元组是静态的,并且如果函数的其他部分的逻辑关闭,元组函数会输出与列表函数相同的值。

这是怎么发生的?

回答

2

originalPos = pos不会创建一个新的列表,它只会给现有列表一个新的名称。要创建新列表,您可以使用空的list slice

originalPos = pos[:] 

编辑:它看起来像在Python 3.3中加入明确的copy方法。

originalPos = pos.copy() 
0

这里的区别是:

originalPos = pos 

你只需要使用一个参考,即originalPospos两个名称相同的对象。

将其更改为:

originalPos = pos[:] 

,你会得到:

>>> ticking_as_list() 
[110, 110] 

这是相同的结果作为元组版本。

1
if ticking: 
     originalPos = pos 
     ticking = False 

第二条语句使得可变originalPos参考相同列表作为pos,因此从那里改变一个也改变另一个。您可能想要复制pos中的实际值,因此take a look at this answer

总之

originalPos = pos[:] 

应该正常工作。