Список Python ([]) и []

from cs1graphics import *
from math import sqrt

numLinks = 50
restingLength = 20.0
totalSeparation = 630.0
elasticityConstant = 0.005
gravityConstant = 0.110
epsilon     = 0.001

def combine(A,B,C=(0,0)):
    return (A[0] + B[0] + C[0], A[1] + B[1] + C[1])

def calcForce(A,B):
    dX = (B[0] - A[0])
    dY = (B[1] - A[1])
    distance = sqrt(dX*dX+dY*dY)
    if distance > restingLength:
        stretch = distance - restingLength
        forceFactor = stretch * elasticityConstant
    else:
        forceFactor = 0
    return (forceFactor * dX, forceFactor * dY)                 #return a tuple


def drawChain(chainData, chainPath, theCanvas):
    for k in range(len(chainData)):
        chainPath.setPoint(Point(chainData[k][0], chainData[k][1]),k)
    theCanvas.refresh()                             #refresh canvas

chain = []                                                             #chain here
for k in range(numLinks + 1):
    X = totalSeparation * k / numLinks
    chain.append( (X,0.0) )

paper = Canvas(totalSeparation, totalSeparation)
paper.setAutoRefresh(False)
curve = Path()
for p in chain:
    curve.addPoint(Point(p[0], p[1]))
paper.add(curve)
graphicsCounter = 100

somethingMoved = True
while somethingMoved:
    somethingMoved = False
    oldChain = list(chain)                                             #oldChain here
    for k in range(1, numLinks):
        gravForce = (0, gravityConstant)
        leftForce = calcForce(oldChain[k], oldChain[k-1])
        rightForce = calcForce(oldChain[k], oldChain[k+1])
        adjust = combine(gravForce, leftForce, rightForce)
        if abs(adjust[0]) > epsilon or abs(adjust[1]) > epsilon:
            somethingMoved = True
        chain[k] = combine(oldChain[k], adjust)
    graphicsCounter -= 1
    if graphicsCounter == 0:
        drawChain(chain, curve, paper)
        graphicsCounter = 100

curve.setBorderWidth(2)
drawChain(chain, curve, paper)

Мне сказали, что list([]) == []. Итак, почему этот код делает oldChain = list(chain) вместо oldChain = chain

Это то же самое, поэтому не имеет значения, как это сделать?

Ответ 1

list(chain) возвращает неглубокую копию chain, она эквивалентна chain[:].

Если вы хотите получить мелкую копию списка, используйте list(), он также иногда используется для получения всех значений из итератора.

Разница между y = list(x) и y = x:


Неглубокая копия:

>>> x = [1,2,3]
>>> y = x         #this simply creates a new referece to the same list object
>>> y is x
True
>>> y.append(4)  # appending to y, will affect x as well
>>> x,y
([1, 2, 3, 4], [1, 2, 3, 4])   #both are changed

#shallow copy   
>>> x = [1,2,3] 
>>> y = list(x)                #y is a shallow copy of x
>>> x is y     
False
>>> y.append(4)                #appending to y won't affect x and vice-versa
>>> x,y
([1, 2, 3], [1, 2, 3, 4])      #x is still same 

DeepCopy:

Обратите внимание, что если x содержит изменяемые объекты, то просто list() или [:] недостаточно:

>>> x = [[1,2],[3,4]]
>>> y = list(x)         #outer list is different
>>> x is y          
False

Но внутренние объекты по-прежнему ссылаются на объекты в x:

>>> x[0] is y[0], x[1] is y[1]  
(True, True)
>>> y[0].append('foo')     #modify an inner list
>>> x,y                    #changes can be seen in both lists
([[1, 2, 'foo'], [3, 4]], [[1, 2, 'foo'], [3, 4]])

Поскольку внешние списки отличаются друг от друга, модификация x не влияет на y и наоборот

>>> x.append('bar')
>>> x,y
([[1, 2, 'foo'], [3, 4], 'bar'], [[1, 2, 'foo'], [3, 4]])  

Для этого используйте copy.deepcopy.

Ответ 2

Верно, что list([]) функционально эквивалентен [], создавая новый пустой список.

Но x = list(y) не совпадает с x = y. Формеры делают мелкую копию, а последняя создает новую ссылку на существующий список.

Обратите внимание, что list([]) неэффективен - он создает новый пустой список (делая []), затем копирует его, в результате чего появляется еще один пустой список (делая list(...)), затем освобождает исходный, список.

Ответ 3

oldchain = list(chain)

oldchain указывает на новый список, который не является цепочкой (не тот же объект), но имеет такое же содержимое.
* Как упоминалось в других ответах, это делает oldchain "мелкой копией" цепочки.

oldchain = chain

oldchain просто указывает на цепочку, оба указывают на тот же объект

Однако обратите внимание, что oldchain = [] и oldchain = list() функционально одинаковы, поскольку оба создают пустой список. Это становится другим, когда задействованы другие ссылки (т.е. chain).

Ответ 4

Если это помогает, вот объяснение, взятое непосредственно со страницы 189 книги (объектно-ориентированное программирование на Python), сразу же ниже представления части кода:

"Важная тонкость в нашем подходе видна в строке 52. Эта строка заставляет oldChain быть копией цепочки. Обратите внимание, что это совсем другая семантика из команды oldChain = chain, которая просто сделает идентификатор ссылки oldChain один и тот же базовый список. Необходимость в этой копии выглядит следующим образом: внутренний цикл for используется для повторного подсчета положения каждой внутренней точки цепочки один за другим. Мы хотим сделать все эти вычисления на основе когерентного состояния Если бы мы не сделали копию, мы столкнулись бы со следующей проблемой: настройка на вторую точку в цепочке зависит от положений первой и третьей точек. Предположим, что мы должны были выполнить эту настройку, а затем продолжить Следующим шагом будет рассчитать корректировку третьей точки, которая зависит от позиций второй и четвертой точек. Но теперь будет несоответствие между предыдущей позицией второй точки и ее обновленной позицией. использование предыдущее положение второй точки для согласованности. По этой причине мы вычисляем все силы, основанные на копии старой цепи".