2016-11-26 17 views
38

Ai đó có thể giải thích những điều sau đây?Có sự khác biệt nào giữa [] và danh sách() khi sử dụng id() không?

Tại sao id giống nhau, nhưng các danh sách khác nhau?

>>> [] is [] 
False 
>>> id([]) == id([]) 
True 

Có sự khác biệt trong tạo danh sách không?

>>> id(list()) == id(list()) 
False 
>>> id([]) == id([]) 
True 

Tại sao điều này xảy ra? Tôi nhận được hai danh sách khác nhau. Tại sao không chỉ một, hoặc ba hoặc nhiều hơn?

>>> [].__repr__ 
<method-wrapper '__repr__' of list object at 0x7fd2be868128> 
>>> [].__repr__ 
<method-wrapper '__repr__' of list object at 0x7fd2be868170> 
>>> [].__repr__ 
<method-wrapper '__repr__' of list object at 0x7fd2be868128> 
>>> [].__repr__ 
<method-wrapper '__repr__' of list object at 0x7fd2be868170> 

Trả lời

76

Bạn đã sử dụng id() sai. id([]) lấy id bộ nhớ của đối tượng là bị hủy ngay lập tức. Sau khi tất cả, không có gì là tham chiếu nó nữa sau khi id() được thực hiện với nó. Vì vậy, lần sau khi bạn sử dụng id([]) Python thấy cơ hội sử dụng lại bộ nhớ và lo lắng, các địa chỉ đó thực sự giống nhau.

Tuy nhiên, đây là chi tiết triển khai, bạn không thể dựa vào và không phải lúc nào cũng có thể sử dụng lại địa chỉ bộ nhớ.

Lưu ý rằng id() giá trị này chỉ độc đáo cho tuổi thọ của đối tượng, xem documentation:

Đây là một số nguyên mà được đảm bảo là duy nhất và liên tục cho đối tượng này trong suốt cuộc đời của nó. Hai đối tượng có thời gian tồn tại không chồng chéo có thể có cùng giá trị id().

(Vùng nhấn mạnh đậm).

Điều đó id(list()) không thể tái sử dụng vị trí bộ nhớ có thể do đột biến đống bổ sung gây ra bằng cách đẩy khung hiện tại trên ngăn xếp để gọi hàm, sau đó bật lại khi trả lại cuộc gọi list().

Cả hai []list() tạo new đối tượng danh sách trống; nhưng bạn cần phải đầu tiên tạo ra tài liệu tham khảo cho những danh sách riêng biệt (đây ab):

>>> a, b = [], [] 
>>> a is b 
False 
>>> id(a) == id(b) 
False 
>>> a, b = list(), list() 
>>> a is b 
False 
>>> id(a) == id(b) 
False 

Cùng xảy ra khi bạn sử dụng [].__repr__. Các thông dịch Python tương tác có một cái tên toàn cầu đặc biệt, _, mà bạn có thể sử dụng để tham khảo các kết quả cuối cùng được sản xuất:

>>> [].__repr__ 
<method-wrapper '__repr__' of list object at 0x10e011608> 
>>> _ 
<method-wrapper '__repr__' of list object at 0x10e011608> 

Điều đó tạo ra một tài liệu tham khảo thêm, vì vậy phương pháp __repr__, và mở rộng ra, danh sách trống mà bạn đã tạo cho nó, vẫn được coi là hoạt động. Vị trí bộ nhớ không được giải phóng và không có sẵn cho danh sách tiếp theo bạn tạo.

Nhưng thực hiện lại [].__repr__, bây giờ Python liên kết _ với đối tượng phương pháp mới đó. Đột nhiên, phương thức __repr__ trước đó không còn được tham chiếu bởi bất cứ điều gì và có thể được giải phóng, và do đó là đối tượng danh sách.

Lần thứ ba bạn thực hiện [].__repr__ vị trí bộ nhớ đầu tiên là có sẵn một lần nữa để tái sử dụng, vì vậy Python không chỉ rằng:

>>> [].__repr__ # create a new method 
<method-wrapper '__repr__' of list object at 0x10e00cb08> 
>>> _   # now _ points to the new method 
<method-wrapper '__repr__' of list object at 0x10e00cb08> 
>>> [].__repr__ # so the old address can be reused 
<method-wrapper '__repr__' of list object at 0x10e011608> 

Bạn không bao giờ tạo ra hơn hai danh sách; cái trước (vẫn được tham chiếu bởi _) và cái hiện tại. Nếu bạn muốn xem thêm các vị trí bộ nhớ, hãy sử dụng các biến để thêm một tham chiếu khác.

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