2013-06-15 14 views

Trả lời

12

Biểu thức danh sách nhiệm vụ được đánh giá từ trái sang phải khi gán.

Đây là những gì sẽ xảy ra:

  • Các tay thể hiện đúng được đánh giá để mang lại (4, 2)
  • a[a.index(2)] được đánh giá để gán 4 đến, a[2] bị thay đổi, danh sách này trở nên [1, 4, 3, 4, 5, 6, 7]
  • a[a.index(4)] là được đánh giá để chỉ định 2 cho, a[2] bị thay đổi lần nữa vì đó là vị trí đầu tiên 4 quay lại [1, 2, 3, 4, 5, 6, 7].

Bạn có thể thấy điều này trong mã Python byte tháo rời:

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

Bởi chỉ số hướng dẫn 59, Python đã đánh giá biểu thức bên phải phía; tiếp theo là các bài tập. Bạn có thể thấy rằng a.index(2) (63-72) được đánh giá trước tiên, sau đó STORE_SUBSCR lưu trữ 4 và chỉ sau đóa.index(4) được đánh giá (hướng dẫn 79-85).

Cách giải quyết là để gọi .index()lần cho mỗi giá trị, và lưu trữ các chỉ số trong các biến:

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

THanks cho câu trả lời! Sau đó, làm cách nào để hoán đổi 2 và 4 trong Danh sách Nếu tôi chỉ có thể truy cập vào các giá trị chỉ mục của nó? –

1

Để tránh điều này, bạn có thể lưu trữ các kết quả của .index() cuộc gọi trong các biến, sau đó làm trao đổi với họ:

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

Bằng cách đó bạn cũng tránh gọi phương thức đó ba lần khi đã đủ.

5

Câu trả lời của Martijn đã hoàn tất và giải thích sự cố bạn đang gặp phải. Nếu bạn vẫn đang tự hỏi làm thế nào để viết mã mà những gì bạn muốn, hãy thử một cái gì đó như thế này:

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

Ý tưởng ở đây là về cơ bản chỉ để lưu trữ các giá trị index trở lại trong một cái gì đó bên ngoài danh sách bản thân. Lưu các chỉ mục một cách riêng biệt như thế này tránh tình trạng cuộc đua bạn đang gặp phải.

+0

Điều này vẫn gọi '.index()' hai lần quá thường xuyên đối với khẩu vị của tôi :) –

+0

Tôi đang nhắm đến sự rõ ràng trong ngắn gọn. :) – theJollySin

+0

Đủ công bằng :) +1 –