【问题标题】:List values changing where they should remain constant列出值在应该保持不变的地方发生变化
【发布时间】:2016-03-22 00:57:46
【问题描述】:

我之前在玩一些代码,发现了一些很奇怪的东西,我无法解释它。

以下是两个除了一件事之外完全相同的功能。变量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 的值,并在每次 x 可被 50 整除时向它们添加 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

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

发生这种情况的原因是什么?

【问题讨论】:

    标签: python list tuples


    【解决方案1】:

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

    originalPos = pos[:]
    

    编辑:看起来像在 Python 3.3 中添加了显式的 copy 方法。

    originalPos = pos.copy()
    

    【讨论】:

      【解决方案2】:
          if ticking:
              originalPos = pos
              ticking = False
      

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

      总之

      originalPos = pos[:]
      

      应该可以正常工作。

      【讨论】:

        【解决方案3】:

        区别就在这里:

        originalPos = pos
        

        您只需使用一个引用,即originalPospos 是同一个对象的两个名称。

        改成:

        originalPos = pos[:]
        

        你会得到:

        >>> ticking_as_list()
        [110, 110]
        

        这与元组版本的结果相同。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2022-07-29
          • 1970-01-01
          • 2014-11-29
          • 2020-10-31
          • 2014-03-01
          • 2020-09-14
          • 1970-01-01
          • 2021-08-02
          相关资源
          最近更新 更多