2013-06-15 10 views
7

Próbowałem następujący kod w python IDLE. Ale nie znalazłem elementów zamienionych.Jak używać list zapytań [list.index ('')] w pythonie

>>> a = [1,2,3,4,5,6,7] 
>>> if(a.index(2)<a.index(4)): 
...  a[a.index(2)],a[a.index(4)] = a[a.index(4)],a[a.index(2)] 

Zgodnie z kodem, powinien odwrócić pozycje 2 i 4. Popraw mnie Jeśli się mylę.

Odpowiedz

12

Wyrażenia listy przydziału są oceniane od lewej do prawej podczas przypisywania.

Oto co się dzieje:

  • Prawo-ręka-wyrażenie jest analizowany w celu uzyskania (4, 2)
  • a[a.index(2)] ocenia przypisać 4 się, a[2] zmienia, staje się lista [1, 4, 3, 4, 5, 6, 7]
  • a[a.index(4)] jest ocenione, aby przypisać 2 do, a[2] został ponownie zmieniony ponieważ jest to teraz pierwsza pozycja 4 powraca do [1, 2, 3, 4, 5, 6, 7].

Można to zobaczyć w zdemontowanego kodu bajtowego Python:

>>> def foo(): 
...  a = [1,2,3,4,5,6,7] 
...  a[a.index(2)],a[a.index(4)] = a[a.index(4)],a[a.index(2)] 
... 
>>> import dis 
>>> dis.dis(foo) 
    2   0 LOAD_CONST    1 (1) 
       3 LOAD_CONST    2 (2) 
       6 LOAD_CONST    3 (3) 
       9 LOAD_CONST    4 (4) 
      12 LOAD_CONST    5 (5) 
      15 LOAD_CONST    6 (6) 
      18 LOAD_CONST    7 (7) 
      21 BUILD_LIST    7 
      24 STORE_FAST    0 (a) 

    3   27 LOAD_FAST    0 (a) 
      30 LOAD_FAST    0 (a) 
      33 LOAD_ATTR    0 (index) 
      36 LOAD_CONST    4 (4) 
      39 CALL_FUNCTION   1 
      42 BINARY_SUBSCR  
      43 LOAD_FAST    0 (a) 
      46 LOAD_FAST    0 (a) 
      49 LOAD_ATTR    0 (index) 
      52 LOAD_CONST    2 (2) 
      55 CALL_FUNCTION   1 
      58 BINARY_SUBSCR  
      59 ROT_TWO    
      60 LOAD_FAST    0 (a) 
      63 LOAD_FAST    0 (a) 
      66 LOAD_ATTR    0 (index) 
      69 LOAD_CONST    2 (2) 
      72 CALL_FUNCTION   1 
      75 STORE_SUBSCR   
      76 LOAD_FAST    0 (a) 
      79 LOAD_FAST    0 (a) 
      82 LOAD_ATTR    0 (index) 
      85 LOAD_CONST    4 (4) 
      88 CALL_FUNCTION   1 
      91 STORE_SUBSCR   
      92 LOAD_CONST    0 (None) 
      95 RETURN_VALUE   

wskaźnikiem instrukcji 59, Python oceniano ekspresję prawostronną boczną; następne są zadania. Najpierw jest oceniany a.index(2) (63-72), a następnie STORE_SUBSCR przechowuje 4 i tylko , a następniea.index(4) jest oceniany (instrukcje 79-85).

Rozwiązaniem jest wywołanie .index()raz dla każdej wartości i przechowywanie indeksów zmiennych:

index_two, index_four = a.index(2), a.index(4) 
if index_two < index_four: 
    a[index_two], a[index_four] = a[index_four], a[index_two] 
+0

Dziękuję za odpowiedź! Następnie, jak mogę zamienić 2 i 4 na liście, jeśli mogę uzyskać dostęp tylko do jej wartości indeksu? –

1

Aby tego uniknąć, można zapisać na wynik rozmów .index() w zmiennych, a następnie wykonaj zamień z nimi:

>>> a = [1,2,3,4,5,6,7] 
>>> i2 = a.index(2) 
>>> i4 = a.index(4) 
>>> if i2<i4: 
...  a[i2], a[i4] = a[i4], a[i2] 
>>> a 
[1, 4, 3, 2, 5, 6, 7] 

W ten sposób unikniesz wywoływania tej metody trzy razy, gdy raz wystarczy.

5

Odpowiedź Martijna jest kompletna i wyjaśnia występujący problem. Jeśli wciąż zastanawiasz się, jak napisać kod, który robi to, co chcesz, spróbuj coś takiego:

if (a.index(2) < a.index(4)): 
    x,y = a.index(4),a.index(2) 
    a[x],a[y] = a[y],a[x] 

Chodzi o to, w zasadzie tylko do przechowywania wartości zwracanych index w czymś zewnętrznym samej listy. Zapisywanie indeksów osobno w ten sposób pozwala uniknąć stanu wyścigowego, który miałeś.

+0

To wciąż wywołuje '.index()' dwa razy za często na mój gust :) –

+0

Dążę do jasności nad zwięzłością. :) – theJollySin

+0

Wystarczająco fair :) +1 –