2011-11-18 17 views
6

Lấy mã sauTôi nghĩ Python đã truyền mọi thứ bằng cách tham khảo?

#module functions.py 
def foo(input, new_val): 
    input = new_val 

#module main.py 
input = 5 
functions.foo(input, 10) 

print input 

Tôi nghĩ hiện nay đầu vào sẽ là 10. Tại sao đây không phải là trường hợp?

+0

Bạn có thể gây nhầm lẫn cho chính mình bằng cách gọi biến cục bộ là "đầu vào" trong định nghĩa hàm foo. Ngoài ra, những gì Sven nói trong câu trả lời. – phkahler

+6

Bất cứ nơi nào bạn đọc rằng Python chuyển mọi thứ bằng tham chiếu, chúng đều sai. –

Trả lời

13

Mọi thứ được chuyển theo giá trị, nhưng giá trị đó là tham chiếu đến đối tượng gốc. Nếu bạn sửa đổi đối tượng, các thay đổi sẽ hiển thị cho người gọi, nhưng bạn không thể gán lại tên. Hơn nữa, nhiều đối tượng không thay đổi (ints, float, string, tuples).

+8

"[Python thành ngữ] (http://python.net/~goodger/projects/pycon/2007/idiomatic/handout.html#other-languages-have-variables)" minh họa hiện tượng này tốt. –

+1

Python không gọi theo giá trị hoặc gọi theo tham chiếu, hãy xem câu trả lời của tôi để biết chi tiết. –

+1

@skyhisi: Câu trả lời của bạn về bản chất giống như của tôi, ngoại trừ việc sử dụng cụm từ không chuẩn "gọi theo đối tượng", mà tôi cố ý tránh vì nó không giải thích được bất kỳ thứ gì. –

8

Bên trong foo, bạn đang ràng buộc tên địa phương input với một đối tượng khác (10). Trong ngữ cảnh gọi, tên input vẫn đề cập đến đối tượng 5.

5

Chuyển nhượng bằng Python không sửa đổi một đối tượng tại chỗ. Nó đặt lại tên để sau input = new_val, biến cục bộ input nhận giá trị mới.

Nếu bạn muốn thay đổi "bên ngoài" input, bạn sẽ phải quấn nó bên trong một đối tượng có thể thay đổi như danh sách một phần tử:

def foo(input, new_val): 
    input[0] = new_val 

foo([input]) 

Python không làm pass-by-reference chính xác cách thức tham chiếu C++ truyền đi. Trong trường hợp này ít nhất, nó nhiều hơn, nếu như tất cả các đối số là một con trỏ trong C/C++:

// effectively a no-op! 
void foo(object *input, object *new_val) 
{ 
    input = new_val; 
} 
+0

cảm ơn câu trả lời của mọi người ... phương pháp này mà bạn đề xuất có vẻ gần như là hack, thủ tục chuẩn này có phải không? có cách nào khác để sửa đổi các loại bất biến có nhiều chất pythonic hơn không? (Tôi đoán 'sửa đổi các loại bất biến' câu trả lời của riêng tôi nhưng tôi sẽ hỏi anyway ...) – Ferguzz

+0

@Ferguzz Bạn không thể sửa đổi các đối tượng bất biến theo định nghĩa. Nhưng đó thực sự là những gì bạn muốn hỏi? Cho đến nay, các đối tượng bất biến thậm chí còn chưa được đề cập đến. Thực tế là 'var = ...' không sửa đổi bất kỳ đối tượng hoặc biến nào khác không liên quan gì đến tính bất biến. Bạn chỉ đơn giản là không thể thực hiện một biến gán thay đổi một biến khác giống như bạn không thể thực hiện thay đổi cho một danh sách ảnh hưởng đến danh sách khác. – delnan

+0

tôi đã đề cập đến dòng trong câu trả lời này 'bọc nó bên trong một đối tượng có thể thay đổi như danh sách'. Tôi đã cố gắng để hỏi, là có một cách để sửa đổi các biến như trong bài gốc của tôi, mà không làm điều này? – Ferguzz

3

Python không phải là giá trị cuộc gọi-by-, hoặc gọi theo tham khảo, đó là Call By Object.

"Lập luận được thông qua bằng cách gọi-by-chia sẻ, tương tự để gọi-by-value, trừ rằng các đối số là đối tượng và có thể thay đổi chỉ khi chúng có thể thay đổi."

+1

Tóm tắt hay, nhưng tôi vẫn tin rằng call-by-object không khác với call-by-value, với tất cả các giá trị "" được xử lý (~ = con trỏ) đến các đối tượng. – Kos

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