2012-01-07 26 views
5

Tôi đã dành 2 giờ cuối cùng cho điều này và tôi có thể đã đọc mọi câu hỏi ở đây liên quan đến các biến được chuyển đến hàm. Vấn đề của tôi là vấn đề chung của tham số/đối số bị ảnh hưởng bởi các thay đổi được thực hiện bên trong hàm, mặc dù tôi đã xóa tham chiếu/bí danh bằng cách sử dụng variable_cloned = variable[:] trong hàm để sao chép nội dung mà không cần tham chiếu.Đối số/tham số đã qua trong hàm vẫn đang được thay đổi sau khi xóa tham chiếu/bí danh

Đây là mã:

def add_column(m):  
    #this should "clone" m without passing any reference on  
    m_cloned = m[:] 
    for index, element in enumerate(m_cloned): 
     # parameter m can be seen changing along with m_cloned even 
     # though 'm' is not touched during this function except to 
     # pass it's contents onto 'm_cloned'   
     print "This is parameter 'm' during the for loop...", m 
     m_cloned[index] += [0] 
    print "This is parameter 'm' at end of for loop...", m  
    print "This is variable 'm_cloned' at end of for loop...", m_cloned 
    print "m_cloned is m =", m_cloned is m, "implies there is no reference" 
    return m_cloned 

matrix = [[3, 2], [5, 1], [4, 7]] 
print "\n" 
print "Variable 'matrix' before function:", matrix 
print "\n" 
add_column(matrix) 
print "\n" 
print "Variable 'matrix' after function:", matrix 

Những gì tôi đang nhận thấy là các tham số 'm' trong hàm đang thay đổi như thể là một bí danh của m_cloned - nhưng như xa như tôi có thể nói tôi có loại bỏ bí danh với dòng đầu tiên của hàm. Ở khắp mọi nơi khác tôi đã xem trực tuyến dường như đề nghị rằng dòng này sẽ đảm bảo không có tham chiếu đến tham số - nhưng nó không hoạt động.

Tôi chắc rằng tôi đã mắc phải một lỗi đơn giản nhưng sau 2 giờ tôi không nghĩ mình sẽ tìm thấy nó.

+1

"... mặc dù tôi đã xóa tham chiếu/bí danh bằng cách sử dụng variable_cloned = biến [:] trong hàm để sao chép nội dung mà không cần tham chiếu. " Điều này làm cho 'variable_cloned' tham chiếu đến một danh sách riêng biệt từ' biến', nhưng hai danh sách sẽ chứa nội dung giống nhau: tham chiếu đến ba danh sách (2 mục) của bạn. –

Trả lời

9

Dường như bạn cần một deepcopy, thay vì một bản sao cạn, đó là những gì [:] mang đến cho bạn:

from copy import deepcopy 
list2 = deepcopy(list1) 

Dưới đây là một ví dụ còn so sánh hai loại bản sao:

from copy import deepcopy 

list1 = [[1], [1]] 
list2 = list1[:] # while id(list1) != id(list2), it's items have the same id()s 
list3 = deepcopy(list1) 

list1[0] += [3] 

print list1 
print list2 
print list3 

Đầu ra:

[[1, 3], [1]] # list1 
[[1, 3], [1]] # list2 
[[1], [1]]  # list3 - unaffected by reference-madness 
+0

Wow cảm ơn, tôi sẽ không bao giờ có mặt ở đó một mình. Tôi đang xem [link] (http://docs.python.org/library/copy.html) mà dường như phần nào giải thích sự khác biệt giữa bản sao sâu và nông nhưng tôi không chắc nó có ý nghĩa gì - tôi nên làm sâu sắc mỗi khi tôi vượt qua một biến cho một chức năng? – FiveAlive

+1

@FiveAlive Không nhất thiết. Đôi khi bạn muốn giữ tham chiếu đến đối tượng "con". Đôi khi điều đó không quan trọng (khi giao dịch với "trẻ em" bất biến), vì những thứ như chuỗi/int không thể thay đổi giá trị, nhưng thay vào đó được thay thế bằng bản sao mới, điều này sẽ không thành vấn đề trong trường hợp của bạn. "Biết" là một nửa trận chiến (họ nói), bây giờ bạn đã biết, tôi chắc chắn bạn sẽ chú ý đến thời gian tới với những gì bạn cần. –

+0

Cảm ơn một lần nữa, điều đó đã xóa mọi thứ cho tôi :) – FiveAlive

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