2012-03-20 40 views
7

*** CHỈNH SỬA: Tôi đã bất cẩn trong các ví dụ ban đầu của mình. Hành vi xảy ra không phải khi tôi thêm danh sách A vào chính nó, mà đúng hơn là khi tôi thêm một danh sách chứa danh sách A đến A. Vui lòng xem các ví dụ đã chỉnh sửa bên dưới.Danh sách dấu ba chấm [...] và nối một danh sách vào chính nó trong Python


Tôi cố gắng để hiểu làm thế nào danh sách lược (những danh sách đó xuất hiện như [...] và xảy ra khi bạn có một danh sách tài liệu tham khảo chính nó) làm việc trong Python (2).

Đặc biệt, tôi muốn biết tại sao, nếu A là một danh sách, A = A + A dường như làm việc khác nhau để A += A (và A.append(A))

Đó là, tại sao bạn nhận được:

>>> a = [1, 2] 
>>> a = a + [a] 
>>> a 
[1, 2, [1, 2]] 

vs .

>>> a = [1, 2] 
>>> a += [a] 
>>> a 
[1, 2, [...]] 

(Lưu ý rằng a.append (a) dường như làm việc đối với tôi chỉ vì sau đó đã làm.)

Bất kỳ thông tin tổng quát bổ sung nào khác về hiện tượng danh sách hình elip này cũng sẽ được đánh giá cao nếu nó giúp làm rõ mọi thứ.

Cảm ơn.

+0

http://stackoverflow.com/questions/2347265/what-does-plus-equals-do-in-python – Dogbert

+1

'a = [1, 2]; a + = a' sẽ tạo '[1, 2, 1, 2]', không phải '[1, 2, [1, 2]'. Xem câu hỏi trùng lặp. – khachik

+1

Cái gọi là trùng lặp không thảo luận về danh sách dấu chấm lửng * ở tất cả *. – Marcin

Trả lời

6

Edit: (để giải quyết các vấn đề bổ sung nêu ra bởi chỉnh sửa cho câu hỏi):

a = a + ba += b không phải là những hoạt động tương tự. Trước đây, thực hiện a.__add__(b), sau đó thực hiện a.__iadd__(b) ("bổ sung tại chỗ").

Sự khác biệt giữa hai là trước đây luôn tạo đối tượng mới (và rebinds tên a thành đối tượng mới) trong khi sau này sửa đổi đối tượng tại chỗ (nếu có thể và với danh sách, nó có thể).

Để minh họa điều này, chỉ cần nhìn vào địa chỉ của đối tượng của bạn:

>>> a = [1, 2] 
>>> id(a) 
34660104 
>>> a = a + [a] 
>>> id(a) 
34657224 
>>> id(a[2]) 
34660104 

Các "mới" a được xây dựng từ đầu, đầu tiên lấy giá trị từ danh sách cũ a, sau đó concatenating tham chiếu đến đối tượng cũ với nó.

Contrast này để:

>>> a = [1, 2] 
>>> id(a) 
34658632 
>>> a += [a] 
>>> id(a) 
34658632 
>>> id(a[2]) 
34658632 

(Cũ câu trả lời, giải thích tài liệu tham khảo theo chu kỳ):

Hãy xem xét điều này:

>>> a = [1, 2]; a += a 
>>> a 
[1, 2, 1, 2] 
>>> a = [1, 2]; a.extend(a) 
>>> a 
[1, 2, 1, 2] 
>>> a = [1, 2]; a += [a] 
>>> a 
[1, 2, [...]] 
>>> a = [1, 2]; a.append(a) 
>>> a 
[1, 2, [...]] 

Vì vậy, để tóm tắt phần đầu:

Đối với danh sách, a += a tương đương với việc gọi a.extend(a) sửa đổi a tại chỗ, thêm bản sao của các thành phần được tìm thấy trong a khi bắt đầu thao tác này.

Ngược lại, a += [a] tương ứng với a.append(a), cả hai đều tạo ra một tài liệu tham khảo vào danh sách a (i. E. Một con trỏ đến địa chỉ của nó trong bộ nhớ) và thêm rằng vào danh sách. Mà cấu thành một cái gọi là "tham chiếu tuần hoàn".

Nếu bạn đã nhìn vào các đại diện nội bộ của a tại thời điểm đó, nó sẽ giống như thế này:

a: Reference to a list object at address 0xDEADBEEF 
a[0]: Reference to the integer object "1" 
a[1]: Reference to the integer object "2" 
a[2]: Reference to the same list object at address 0xDEADBEEF 

phiên bản Cũ Python (pre-1.5.1) không đủ thông minh để phát hiện , vì vậy nếu bạn đã làm một số print a, bạn sẽ nhận được [1, 2, [1, 2, [1, 2, [1, 2, [1, 2, [1, 2, ... v.v. trong một vòng lặp vô hạn. Kể từ Python 1.5.1, trình thông dịch phát hiện điều này, thay vào đó hãy in [1, 2, [...]].

0

xem xét như sau:

In [179]: a = [1, 2] 

In [180]: a+=a 

In [181]: a 
Out[181]: [1, 2, 1, 2] 

In [182]: a.append(a) 

In [183]: a 
Out[183]: [1, 2, 1, 2, [...]] 

In [184]: a[5] 
----------------------------------------------- 
IndexError        Trace 
C:\Users\Marcin\Documents\oneclickcos\oneclickc 
----> 1 a[5] 

IndexError: list index out of range 

In [185]: a[4] 
Out[185]: [1, 2, 1, 2, [...]] 

In [186]: a[3] 
Out[186]: 2 

In [187]: a[4] 
Out[187]: [1, 2, 1, 2, [...]] 

In [188]: a 
Out[188]: [1, 2, 1, 2, [...]] 

In [189]: a[4][3] 
Out[189]: 2 

In [190]: a[4][4] 
Out[190]: [1, 2, 1, 2, [...]] 

In [191]: a[4][5] 
----------------------------------------------- 
IndexError        Trace 
C:\Users\Marcin\Documents\oneclickcos\oneclickc 
----> 1 a[4][5] 

IndexError: list index out of range 

In [192]: a[4][4] 
Out[192]: [1, 2, 1, 2, [...]] 

In [193]: a = [1, 2] 

In [194]: a+=a 

In [195]: a 
Out[195]: [1, 2, 1, 2] 

In [196]: a 
Out[196]: [1, 2, 1, 2] 

In [197]: a 
Out[197]: [1, 2, 1, 2] 

In [198]: a.append(a) 

In [200]: a 
Out[200]: [1, 2, 1, 2, [...]] 

In [201]: a.append(a) 

In [202]: a 
Out[202]: [1, 2, 1, 2, [...], [...]] 

In [203]: a[4] 
Out[203]: [1, 2, 1, 2, [...], [...]] 

In [204]: a[5] 
Out[204]: [1, 2, 1, 2, [...], [...]] 

In [205]: id(a) 
Out[205]: 64692680L 

In [206]: id(a[5]) 
Out[206]: 64692680L 

In [207]: id(a[4]) 
Out[207]: 64692680L 

In [208]: id(a) == id(a[4]) and id(a[4]) == id(a[5]) 
Out[208]: True 

Thông báo đầu tiên của tất cả những gì += không tạo ra một danh sách lược.

Thứ hai, nó có thể được nhìn thấy rằng ellipsis-list chỉ ra rằng accesing khe đó sẽ trở lại chính xác cùng một danh sách - ellipsis-list đại diện cho một con trỏ đến danh sách bên ngoài (hoặc, gần như chắc chắn một danh sách bên ngoài nếu có nhiều cấp độ làm tổ).

Các vấn đề liên quan