2013-07-11 13 views
10
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) 

Powiedziano mi, że list([]) == []. Więc dlaczego ten kod robi
oldChain = list(chain) zamiast oldChain = chainLista pytonów ([]) i []

to samo, więc nie ma znaczenia, tak czy inaczej to zrobić?

+2

Czy to nie twój kod? – 2rs2ts

+4

Byłoby lepiej, gdybyś opublikował tylko fragment kodu odpowiadający pytaniu. natychmiast wyjaśnij, o której linii mówisz – shx2

+0

@ 2rs2ts jego kod z Object-Oriented Programming w języku Python – ealeon

Odpowiedz

16

list(chain) zwraca płytką kopię chain, jest to odpowiednik chain[:].

Jeśli chcesz mieć płytką kopię listy, użyj list(), czasami też używałeś do pobrania wszystkich wartości z iteratora.

Różnica między y = list(x) i y = x:


Płytki kopia:

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

Uwaga tha t jeśli x zawiera zmienny obiektów potem po prostu list() lub [:] nie wystarczą:

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

Ale wewnętrzne obiekty są nadal odniesienia do obiektów w 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]]) 

jako zewnętrzna listach różnią następnie modyfikując x nie wpłynie Y i vice versa

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

Aby poradzić sobie z tym stosowanie copy.deepcopy.

+2

Powinieneś rozwinąć na tym przykładzie, aby pokazać d Pomiędzy "a = b" i "a = list (b)" również pod względem odniesienia, wtedy ta odpowiedź byłaby całkiem kompletna. Dodaj przykład pokazujący, że modyfikacja "a" w pierwszym przykładzie "zmodyfikuje b", kontrastuje z drugą instrukcją. –

+0

@ LasseV.Karlsen Zrobione. –

2
oldchain = list(chain) 

oldchain wskazuje na nową listę, która nie jest łańcuchem (nie tym samym obiektem), ale ma tę samą zawartość.
* Jak już wspomniały inne odpowiedzi, czyni to oldchain "płytką kopią" łańcucha.

oldchain = chain 

oldchain tylko wskazuje na łańcuchu, zarówno punkt do samego obiektu

jednak pamiętać, że oldchain = [] i oldchain = list() są funkcjonalnie takie same, ponieważ oba są tworząc pustą listę. Staje się to inne, gdy zaangażowane są inne odniesienia (np. chain).

3

To prawda, że ​​list([]) jest funkcjonalnie równoważne [], przy czym obie tworzą nową pustą listę.

Ale x = list(y) to nie to samo co x = y. Formery tworzą płytką kopię, która tworzy nowe odniesienie do istniejącej listy.

Zauważ, że list([]) jest nieefektywne - tworzy nową listę pustą (wykonując []), a następnie kopiuje to, wynikające z innej pustej listy (przez robi list(...)), następnie dealokuje oryginalnego, bez numeru referencyjnego, listy.

+1

Ludzie mają tendencję do pisania 'lst = []', ale możesz również napisać 'lst = list()', jest to również funkcjonalny odpowiednik. – 2rs2ts

+2

@ 2rs2ts Używanie literałów jest jednak szybszym i lepszym stylem. –

+1

@Lattyware Nie zdawałem sobie sprawy, że to było szybsze, ale 'imeit.timeit (stmt = 'lst = []', number = 100000000)' powodowało '3.7173891067504883' podczas gdy' timeit.timeit (stmt = 'lst = list () ', number = 100000000) 'spowodowało' 12.700881958007812'. Łał! – 2rs2ts

1

Jeśli to nie pomaga, tutaj jest wyjaśnienie zaczerpnięte bezpośrednio ze strony 189 książki (Object Oriented Programming w Pythonie), bezpośrednio pod prezentacji kawałek kodu danego:

„Ważnym subtelność w nasze podejście jest widoczne w wierszu 52. Ta linia powoduje, że oldChain jest kopią łańcucha.Zauważ, że jest to całkiem inna semantyka od polecenia oldChain = chain, która po prostu uczyniłaby identyfikator oldChain odwołującym się do tej samej bazowej listy. ta kopia jest następująca: Wewnętrzna pętla używana jest do ponownego obliczenia pozycji każdego wnętrza łańcucha, jeden po drugim. Chcemy wykonać wszystkie te obliczenia w oparciu o spójny stan łańcucha. glina y, natkniemy się na następujące problemy. Dopasowanie do drugiego punktu łańcucha zależy od pozycji pierwszego i trzeciego punktu. Załóżmy, że dokonamy tego dostosowania, a następnie kontynuujemy. Następnym krokiem byłoby obliczenie dostosowania do trzeciego punktu, który zależy od pozycji drugiego i czwartego punktu. Ale teraz wystąpiłaby rozbieżność między poprzednią pozycją drugiego punktu a jego zaktualizowaną pozycją. Chcemy wykorzystać poprzednią pozycję drugiego punktu dla spójności. Z tego powodu obliczamy wszystkie siły na podstawie kopii starego łańcucha. "

+0

ah Widzę. ale musi być inne wydanie książki? Właśnie sprawdziłem stronę 211 i nie ma tam takiego wyjaśnienia. W rzeczywistości powyższy kod znajduje się na stronie 192 rys. 5.9 i przechodzi bezpośrednio do przeglądu rozdziału zaraz po kodzie bez żadnych wyjaśnień. Niemniej jednak kocham tę książkę do tej pory. – ealeon

+0

Mój błąd na stronie numer (patrzyłem na plik PDF). Komentarz znajduje się na stronie 189, ponieważ podano fragment kodu przed przedstawieniem pełnego programu na stronach 191-192. Edytowałem powyższy numer –