2012-06-14 33 views
7
myVar = ["jhhj", "hgc"] 
myTuple = ([1,2,3], [4,5,6], myVar) 
myVar.append('lololol') 
print myTuple 

Tại sao và làm thế nào để bộ sửa đổi này có thể được sửa đổi bằng cách thêm sau khi xây dựng?Tại sao nội dung của một bộ thay đổi khi tôi thêm vào một danh sách bên trong nó nhưng không thay đổi khi tôi cập nhật một biến?

myVar = "lol" 
myTuple = ([1,2,3], [4,5,6], myVar) 
myVar = "lolol" 
print myTuple 

Tại sao điều này sẽ in ra ([1,2,3], [4,5,6], "lol") thay vì ([1,2,3], [4,5,6], "lolol")?

Trả lời

7

Vâng, hãy để tôi cố gắng giải thích với một số hình ảnh.

Trong Python, mọi thứ đều là một đối tượng. Các đối tượng đó được tham chiếu theo biến. Một số loại đối tượng, chẳng hạn như danh sách và bộ dữ liệu, chỉ lưu trữ các tham chiếu đến các đối tượng khác.

Điều đó nói rằng, khi bạn thực hiện

myVar = ["jhhj", "hgc"] 
myTuple = ([1,2,3], [4,5,6], myVar) 

Bạn nhận được nhiều hay ít kịch bản này:

A tuple pointing to three lists; a list pointing to two strings

Mỗi đối tượng được thể hiện bằng một hộp/hình chữ nhật. Chúng tôi có hai đối tượng chuỗi, "jhhj""hgc". Ngoài ra, chúng tôi có một đối tượng danh sách, được chỉ bởi biến số myVar; danh sách đối tượng này trỏ tới cả hai đối tượng chuỗi. Ngoài ra, chúng tôi có một đối tượng tuple, được tham chiếu bởi myTuple; đối tượng tuple này chỉ hai danh sách khác và danh sách được tham chiếu bởi myVar.

Khi bạn thực hiện

myVar.append('lololol') 

gì xảy ra? Vâng, đối tượng danh sách (có nghĩa là tình cờ được trỏ bởi myVar) bắt đầu tham chiếu một giá trị nhiều hơn, các đối tượng chuỗi "lololol":

A tuple pointing to three lists; a list pointing to two strings; a new string is added to the list

Lưu ý rằng myVar vẫn tham chiếu đối tượng danh sách. Điều đã xảy ra là đối tượng danh sách đã thay đổi.Bạn có thể xem đối tượng danh sách này cả hai từ myVar hoặc từ bộ tuple, bạn sẽ thấy cùng một đối tượng với cùng một thay đổi.

OTOH, khi bạn thực hiện

myVar = "lol" 
myTuple = ([1,2,3], [4,5,6], myVar) 

Bạn nhận được một cái gì đó như thế này:

A tuple pointing to two lists and a string, also pointed by a variable

Bây giờ myVar điểm đến đối tượng chuỗi "lol", cũng như các tài liệu tham khảo tuple nó ở vị trí thứ ba . Bây giờ, nếu bạn thực hiện

myVar = "lolol" 

bạn chỉ cần thực hiện myVar để trỏ đến một đối tượng khác. Các đối tượng tuple vẫn trỏ tới "lol" như trước:

A tuple pointing to two lists and a string, also pointed by a variable. The variable now references another string.

Vì vậy, nếu bạn gán một giá trị mới cho một biến, nó sẽ chỉ thay đổi giá trị được trỏ bởi biến này. Giá trị trước đó được tham chiếu bởi biến sẽ vẫn tồn tại * và bất kỳ biến hoặc đối tượng nào trỏ đến nó sẽ vẫn trỏ đến nó. Chỉ biến phân bổ sẽ thay đổi.

PS: Ngoài ra, I answered a vaguely related question some time ago. Bạn có thể tìm thấy câu trả lời hữu ích.

* Trừ khi được thu thập bởi bộ thu gom rác, nhưng đây là một lịch sử lâu dài khác.

1

Tuples là không thay đổi, vì vậy bạn sẽ cần phải xây dựng một tuple mới nếu bạn muốn thay đổi một trong các thành viên của nó ...

5

Tất cả mọi thứ trong python là các đối tượng.

Vì vậy, khi bạn làm nhiệm vụ ban đầu của bạn

myVar = "lol"

bạn đang đưa ra myVar một tham chiếu đến đối tượng "lol"

Sau đó bạn tạo một tuple. Tuple này trong khe thứ ba có tham chiếu đến "lol"

Sau đó, bạn tạo một đối tượng mới "lolol" và cung cấp cho myVar một tham chiếu đến nó. Các tuple giữ tham chiếu ban đầu của mình để "lol"

+0

vậy làm thế nào đến phụ một danh sách sau đó trong chương trình sửa đổi tuple gốc? –

+0

Bạn đang sửa đổi đối tượng danh sách bên trong tuple –

+1

Bạn không sửa đổi bộ tuple. Bạn đang sửa đổi danh sách thành viên của một bộ tuple. Một cách hơi không chính xác, nhưng hữu ích để xem xét nó là một tuple '([1,2], [3,4])' thực sự là '(address_to_list1, address_to_list2)' Bạn không thể thay đổi địa chỉ, nhưng các danh sách là các đối tượng riêng biệt, có thể thay đổi. –

1

Tuples là không thay đổi nhưng bạn có thể nối chúng lại với nhau thích:

var a = (1, 2) 
var b = a + (3, 4) 
+0

làm thế nào để thêm vào danh sách myVar sau này trong chương trình sửa đổi bộ tuple gốc? –

1

Trong cả hai trường hợp, khi bạn tạo bộ tảo, bạn đang sao chép tham chiếu đến bất kỳ đối tượng nào myvar vào thời điểm đó.

Trong trường hợp đầu tiên, myvar là một đối tượng có thể thay đổi. Bạn có thể thay đổi đối tượng sau khi tham chiếu đến nó đã được lưu trữ trong bộ dữ liệu.

Trong trường hợp thứ hai, myvar là chuỗi không thay đổi. Bạn không thể thay đổi đối tượng, nhưng bạn có thể thay đổi chính những gì myvar đề cập đến. Điều đó không thay đổi đối tượng được chứa bên trong tuple.

1

Đã có một số điểm lớn trong câu trả lời khác mà tôi sẽ không tái lặp một lần nữa, giải thích sự khác biệt giữa tênđối tượng. Tất cả những gì tôi nghĩ là thiếu chính tả khi một số mã Python đang hoạt động trên tên và khi nó đang hoạt động trên các đối tượng.

Điều quan trọng mà bạn cần hiểu là mặc dù chỉ điều ảnh hưởng trực tiếp đến tên là câu lệnh gán [1]. Một câu lệnh gán sẽ đặt lại tên để trỏ đến một đối tượng khác. Tên xuất hiện trong mọi ngữ cảnh khác chỉ là một trạng thái đơn giản cho bất kỳ đối tượng nào mà tên đó bị ràng buộc khi dòng mã đó được thực thi.

Hãy nhìn vào dòng này từ ví dụ của bạn:

myTuple = ([1,2,3], [4,5,6], myVar) 

myTuple xuất hiện ở bên trái của lệnh gán, vì vậy tên myTuple là những gì đang bị ảnh hưởng đó.Mặt khác, myVar nằm bên trong một biểu thức, do đó, đối tượng myVar bị ràng buộc là yếu tố thứ ba của bộ tẩu, không phải là tên myVar.

Do đó, bất kỳ điều gì xảy ra sau đó đến tên myVar không có tác dụng trên bộ dữ liệu. Nhưng miễn là phần tử thứ ba của tuple và myVar đề cập đến cùng một đối tượng, việc thay đổi đối tượng (thông qua myVar hoặc tuple) rõ ràng sẽ ảnh hưởng đến những gì bạn nhận được khi nhìn vào đối tượng thông qua tham chiếu.


[1] Đối với nghiên cứu tiên tiến, defclass báo cáo cũng là "câu lệnh gán" (họ tạo một hàm hoặc một lớp và sau đó gán nó vào tên).

Ngoài ra, các nhà khai thác như +=, *=, vv là đôi khi câu lệnh gán và đôi khi không, tùy thuộc vào loại đối tượng hiện đang được gọi bằng tên trên LHS:

myList = [] 
myList += ['this calls a method on a list object which mutates it in place; the name is not changed'] 

myInt = 1 
myInt += 10 # This rebinds myInt to refer to a new object 11; the object 1 is not changed