2012-03-15 30 views
5

Tôi đang nhầm lẫn với tham chiếu Python. Hãy xem xét ví dụ sau:Python tham chiếu như thế nào?

Nhiệm vụ của tôi: Để chỉnh sửa từng phần tử trong danh sách

d = { 'm': [1,2,3] } 
m = d['m'] 
m = m[1:] # m changes its reference to the new sliced list, edits m but not d (I wanted to change d) 

Tương tự:

d = { 'm': [1,2,3] } 
m = d['m'] 
m = m[0] # As per python referencing, m should be pointing to d['m'] and should have edited d 

Trong python mọi thứ diễn ra bằng cách tham khảo, sau đó khi là một đối tượng mới tạo? Chúng tôi có luôn cần copydeepcopy từ mô-đun copy để tạo bản sao đối tượng không?

Vui lòng làm rõ.

+1

Nếu bạn là người học trực quan, [đây] (http://people.csail.mit.edu/pgbovine/python /) một hướng dẫn tốt – forivall

+0

Nhận xét vô cùng hữu ích Mr. @jordoex - Nghiêm túc Tuyệt vời! –

Trả lời

11

Trong Python một biến không phải là một hộp chứa mọi thứ, nó là tên trỏ đến một đối tượng. Trong mã của bạn:

  • d = { 'm': [1,2,3] } -> liên kết tên d để một cuốn từ điển
  • m = d['m'] -> liên kết tên m vào một danh sách
  • m = m[1:] -> liên kết tên m vào danh sách khác

Dòng thứ ba của bạn không thay đổi m chính nó, nhưng những gì m đang trỏ đến.

Để chỉnh sửa các yếu tố trong danh sách những gì bạn có thể làm là:

m = d['m'] 
for i, item in enumerate(m): 
    result = do_something_with(item) 
    m[i] = result 
+0

Có cách nào khác để chỉnh sửa từng phần tử của danh sách này ngoài 'liệt kê' không? –

+0

"Tên trỏ đến một đối tượng" có thể gây nhầm lẫn, vì "con trỏ" không phải là thuật ngữ Python. Tôi chỉ nói "nó là tên cho một đối tượng". –

+0

"Dòng thứ ba của bạn không tự thay đổi m, nhưng m trỏ tới" có thể không rõ ràng đối với người đọc. Để rõ ràng hơn: "dòng thứ ba thay đổi m từ chỉ đến một điều (d ['m']) để trỏ đến một thứ khác ([2,3])." –

5

Ethan Furman đã làm một công việc tuyệt vời của việc giải thích như thế nào Python internals công việc, tôi sẽ không lặp lại nó.

m thực sự đại diện cho danh sách bên trong từ điển, bạn có thể sửa đổi nó. Bạn không thể chỉ định lại nó cho một cái gì đó mới, đó là những gì sẽ xảy ra khi bạn sử dụng = để cân bằng nó với một lát mới.

Để phân loại ra khỏi phần tử đầu tiên của danh sách ví dụ:

>>> m[0:1] = [] 
>>> d 
{'m': [2, 3]} 
+4

Tôi ghét lái xe bởi downvotes, nếu tôi đã làm điều gì đó sai tôi muốn tìm hiểu lý do tại sao. Câu trả lời này đã được thử nghiệm trong Python 2.7 bằng cách sử dụng một thành ngữ được đề nghị: http://docs.python.org/library/stdtypes.html#mutable-sequence-types –

+0

Tôi nghĩ đó là một cái nhìn sâu sắc tốt Đánh dấu, và tôi không biết tại sao nó đã được downvoted ... –

+2

Để xóa các mục hoặc lát từ một danh sách, tôi thường thích 'del m [0]' rõ ràng hơn. Tất nhiên đây là một sở thích phong cách, và tôi không có ý tưởng tại sao một người nào đó bị downvoted. Tôi đoán là nhiều người trong số những downvotes dường như ngẫu nhiên là kết quả của các màn hình điện thoại thông minh quá nhỏ. –

4

Trong python mọi thứ diễn ra bằng cách tham khảo

Trong Python, tất cả mọi thứ một tài liệu tham khảo, và các tài liệu tham khảo được truyền theo giá trị.

Nếu bạn muốn sử dụng các cụm từ đó. Nhưng những thuật ngữ đó làm cho mọi thứ khó hiểu hơn.

Đơn giản hơn nhiều: trong Python, biến là tên của đối tượng. = được sử dụng để thay đổi tên đối tượng đề cập đến. Phía bên trái có thể tham chiếu đến một phần của đối tượng hiện có, trong trường hợp đó toàn bộ đối tượng được thay đổi bằng cách thay thế phần đó. Điều này là do đối tượng, lần lượt, không thực sự chứa các phần của nó, nhưng thay vào đó có chứa nhiều tên hơn, có thể được gây ra để bắt đầu đề cập đến những thứ khác nhau.

khi nào đối tượng mới được tạo?

Đối tượng được tạo khi chúng được tạo (bằng cách sử dụng hàm tạo lớp hoặc trong trường hợp các kiểu dựng sẵn có đại diện bằng chữ, bằng cách nhập một chữ). Tôi không hiểu làm thế nào điều này có liên quan đến phần còn lại của câu hỏi của bạn.

m = m[1:] # m changes its reference to the new sliced list 

Vâng, tất nhiên. Bây giờ m là kết quả của việc đánh giá m[1:].

edits m but not d (I wanted to change d) 

Vâng, tất nhiên. Tại sao sẽ nó thay đổi d? Đó không phải là một loại phép thuật nào đó, nó đơn giản là kết quả của việc đánh giá d['m']. Chính xác điều tương tự cũng xảy ra trên cả hai dòng.

Hãy xem xét một ví dụ đơn giản hơn.

m = 1 
m = 2 

Điều này có gây ra 1 để trở thành 2? Tất nhiên là không rồi. Số nguyên là không thay đổi. Nhưng cùng một điều đang xảy ra: m được gây ra để đặt tên một điều, và sau đó đặt tên cho một điều khác.

Hoặc, một cách khác: nếu "tham chiếu" đã hoạt động theo cách bạn mong đợi, thì dòng m = m[1:] sẽ đệ quy. Bạn đang mong đợi nó có nghĩa là "bất cứ nơi nào bạn nhìn thấy m, đối xử với nó như thể nó có nghĩa là m[1:]". Vâng, trong trường hợp đó, m[1:] thực sự có nghĩa là m[1:][1:], điều này có nghĩa là m[1:][1:][1:], v.v.

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