9 votes

Python list([]) et []

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)

On m'a dit que list([]) == [] . Alors pourquoi ce code fait
oldChain = list(chain) au lieu de oldChain = chain

c'est la même chose donc ça n'a pas d'importance de le faire d'une façon ou d'une autre ?

16voto

Ashwini Chaudhary Points 94431

list(chain) renvoie une copie superficielle de chain il est équivalent à chain[:] .

Si vous voulez une copie superficielle de la liste, alors utilisez list() Il est aussi parfois utilisé pour récupérer toutes les valeurs d'un itérateur.

Différence entre y = list(x) y y = x :


Copie superficielle :

>>> 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 :

Notez que si x contient des objets mutables, il suffit de list() o [:] ne sont pas suffisants :

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

Mais les objets internes sont toujours des références aux objets de 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]])

Comme les listes externes sont différentes, la modification de x n'affectera pas y et vice-versa.

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

Pour gérer cela, utilisez copy.deepcopy .

3voto

shx2 Points 14025

Il est vrai que list([]) est fonctionnellement équivalent à [] en créant tous deux une nouvelle liste vide.

Mais x = list(y) n'est pas la même chose que x = y . Le premier fait une copie superficielle, et le second crée une nouvelle référence à la liste existante.

Notez que list([]) est inefficace -- il crée une nouvelle liste vide (en faisant [] ), puis la copie, ce qui donne une autre liste vide (en faisant list(...) ), puis désalloue la liste originale, non référencée.

2voto

oldchain = list(chain)

oldchain pointe vers une nouvelle liste qui n'est pas chain (pas le même objet) mais qui a le même contenu.
*Comme d'autres réponses l'ont mentionné, cela fait de oldchain une "copie superficielle" de la chaîne.

oldchain = chain

oldchain ne pointe que vers la chaîne, les deux pointent vers le même objet.

Cependant, notez que oldchain = [] y oldchain = list() sont fonctionnellement les mêmes puisque les deux créent une liste vide. Cela devient différent lorsque d'autres références (ex. chain ) sont impliqués.

1voto

Si cela peut vous aider, voici l'explication tirée directement de la page 189 du livre (Object Oriented Programming in Python), juste en dessous de la présentation du morceau de code donné :

"Une subtilité importante dans notre approche apparaît à la ligne 52. Cette ligne fait en sorte que oldChain soit une copie de la chaîne. Notez que c'est une sémantique très différente de la commande oldChain = chain, qui ferait simplement en sorte que l'identifiant oldChain fasse référence à la même liste sous-jacente. La nécessité de cette copie est la suivante. La boucle for interne est utilisée pour recalculer la position de chaque point intérieur de la chaîne, un par un. Nous voulons effectuer tous ces calculs sur la base d'un état cohérent de la chaîne. Si nous n'avions pas fait de copie, nous rencontrerions le problème suivant. L'ajustement du deuxième point de la chaîne dépend des positions du premier et du troisième point. Supposons que nous fassions cet ajustement et que nous continuions. L'étape suivante consisterait à calculer l'ajustement du troisième point, qui dépend des positions des deuxième et quatrième points. Mais il y aurait maintenant une divergence entre la position précédente du deuxième point et sa position actualisée. Nous voulons utiliser la position précédente du deuxième point pour des raisons de cohérence. Pour cette raison, nous calculons toutes les forces sur la base de la copie de l'ancienne chaîne."

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X