2012-03-14 53 views
25

thể trùng lặp:
Python: How do I pass a variable by reference?Python: Khi nào một biến được truyền theo tham chiếu và khi nào theo giá trị?

Mã của tôi:

locs = [ [1], [2] ] 
for loc in locs: 
    loc = [] 

print locs 
# prints => [ [1], [2] ] 

Tại sao loc không tham khảo các yếu tố của locs?

Python: Mọi thứ được chuyển dưới dạng tham chiếu trừ khi được sao chép rõ ràng [Đây có phải là sự thật không? ]

Vui lòng giải thích .. làm thế nào để python quyết định tham chiếu và sao chép?

Cập nhật:

Làm thế nào để làm gì?

def compute(ob): 
    if isinstance(ob,list): return process_list(ob) 
    if isinstance(ob,dict): return process_dict(ob) 

for loc in locs: 
    loc = compute(loc) # What to change here to make loc a reference of actual locs iteration ? 
  • Locs phải có các phản ứng xử lý cuối cùng!
  • Tôi không muốn sử dụng enumerate, có thể không có nó?
+4

Mọi thứ được truyền theo giá trị, nhưng mọi giá trị chỉ là một tham chiếu;) – wim

Trả lời

17

Mọi thứ trong Python đều được truyền và gán theo giá trị, giống như cách mọi thứ được truyền và gán theo giá trị trong Java. Mỗi giá trị trong Python là một tham chiếu (con trỏ) đến một đối tượng. Đối tượng không thể là giá trị. Nhiệm vụ luôn luôn sao chép giá trị (đó là một con trỏ); hai con trỏ như vậy có thể trỏ đến cùng một đối tượng. Các đối tượng không bao giờ được sao chép trừ khi bạn đang làm một cái gì đó rõ ràng để sao chép chúng.

Đối với trường hợp của bạn, mỗi lần lặp của vòng lặp gán một phần tử của danh sách vào biến loc. Sau đó, bạn gán một thứ khác cho biến số loc. Tất cả các giá trị này là con trỏ; bạn đang chỉ định con trỏ; nhưng bạn không ảnh hưởng đến bất kỳ đối tượng nào theo bất kỳ cách nào.

+0

Theo quan điểm của tôi - Bạn đã mô tả nó là tốt nhất. Chỉ cần cho tôi biết câu trả lời của Bản cập nhật cho câu hỏi - phần bạn đã bỏ lỡ. –

+0

Vậy điều gì xảy ra với số nguyên và số float? Chúng có được coi là những vật không thay đổi được không? Làm thế nào để python quản lý như tôi chắc chắn nó không thể giữ tất cả các conceivable số trong bộ nhớ đã sẵn sàng để được tham chiếu. –

+0

@AndrewS: Số nguyên và phao thực sự không thay đổi (cần phải rõ ràng là chúng không có phương thức tự biến đổi). Tôi không chắc phần thứ hai của bình luận của bạn có nghĩa là gì. – newacct

2

Mọi thứ được truyền bởi đối tượng. Rebinding và mutating là các hoạt động khác nhau.

locs = [ [1], [2] ] 
for loc in locs: 
    del loc[:] 

print locs 
3

Khi bạn nói

loc = [] 

bạn đang rebinding biến loc vào một danh sách rỗng mới được tạo ra

Có lẽ bạn muốn

loc[:] = [] 

nào gán một lát (mà xảy ra để được toàn bộ danh sách) của loc vào danh sách trống

+1

Tôi tin rằng ví dụ cuối cùng này là những gì OP đang tìm kiếm! –

7

Nó không giúp trong Python suy nghĩ về các tham chiếu hoặc giá trị. Không đúng.

Trong Python, biến chỉ là tên. Trong vòng lặp for của bạn, loc chỉ là một tên trỏ đến phần tử hiện tại trong danh sách. Làm loc = [] chỉ cần rebinds tên loc vào một danh sách khác, chỉ để lại phiên bản gốc.

Nhưng vì trong ví dụ của bạn, mỗi phần tử là một danh sách, bạn có thể thực sự đột biến yếu tố đó, và đó sẽ được phản ánh trong danh sách ban đầu:

for loc in locs: 
    loc[0] = loc[0] * 2 
+2

Có thể hữu ích khi đọc * Idiomatic Python * - ["các ngôn ngữ khác có biến, Python có nhãn."] (Http://python.net/~goodger/projects/pycon/2007/idiomatic/handout.html#other -languages-have-variables) Phần còn lại của nó là tốt đọc. ;) –

+0

Cách sửa đổi từng phần tử của vùng chứa? \ –

+0

@Yugal mà một phần của những gì tôi đã viết ở trên không rõ ràng? –

44

Effbot (aka Fredrik Lundh) đã mô tả Kiểu biến đi qua của Python là gọi theo đối tượng: http://effbot.org/zone/call-by-object.htm

Đối tượng được phân bổ trên heap và các con trỏ tới chúng có thể được truyền đi khắp mọi nơi.

  • Khi bạn thực hiện một nhiệm vụ như x = 1000, một mục từ điển được tạo ra ánh xạ chuỗi "x" trong không gian tên hiện tại tới con trỏ đến đối tượng số nguyên chứa một nghìn.
  • Khi bạn cập nhật "x" với x = 2000, một đối tượng số nguyên mới được tạo và từ điển được cập nhật để trỏ vào đối tượng mới. Một nghìn đối tượng cũ không thay đổi (và có thể hoặc không thể sống tùy thuộc vào việc có bất kỳ điều gì khác đề cập đến đối tượng) hay không.
  • Khi bạn thực hiện một nhiệm vụ mới như y = x, một mục nhập từ điển mới "y" được tạo ra trỏ đến cùng một đối tượng như mục nhập cho "x".
  • Các đối tượng như chuỗi và số nguyên là không thay đổi. Điều này đơn giản có nghĩa là không có phương thức nào có thể thay đổi đối tượng sau khi nó được tạo ra. Ví dụ, một khi đối tượng số nguyên một nghìn được tạo ra, nó sẽ không bao giờ thay đổi. Toán được thực hiện bằng cách tạo các đối tượng số nguyên mới.
  • Các đối tượng như danh sách là có thể thay đổi. Điều này có nghĩa rằng nội dung của đối tượng có thể được thay đổi bởi bất cứ điều gì trỏ đến đối tượng. Ví dụ: x = []; y = x; x.append(10); print y sẽ in [10]. Danh sách trống đã được tạo. Cả hai "x" và "y" trỏ đến cùng một danh sách. chắp thêm các biến thể (cập nhật) đối tượng danh sách (như thêm bản ghi vào cơ sở dữ liệu) và kết quả được hiển thị cho cả "x" và "y" (giống như bản cập nhật cơ sở dữ liệu sẽ hiển thị cho mọi kết nối đến cơ sở dữ liệu đó).

Hy vọng làm rõ vấn đề cho bạn.

+1

câu trả lời xuất sắc. – sunqiang

2

Tại sao loc không tham chiếu đến các phần tử của loc?

Đây là. Hoặc ít nhất, nó cũng giống như mọi biến khác trong Python. Biến số Python là tên, không lưu trữ. loc là tên được sử dụng để chỉ các phần tử của [[1,2], [3,4]], trong khi locs là tên đề cập đến toàn bộ cấu trúc.

loc = [] 

này không có nghĩa "nhìn vào điều mà loc tên, và làm cho nó trở thành []". Nó không thể có nghĩa là, vì đối tượng Python là không có khả năng của một thứ như vậy.

Thay vào đó, điều này có nghĩa là "gây ra loc để ngừng là tên cho tên hiện tại và bắt đầu thay vì là tên cho []". (Tất nhiên, nó có nghĩa là số [] cụ thể được cung cấp ở đó, vì nói chung có thể có một số đối tượng trong bộ nhớ giống nhau.)

Tự nhiên, nội dung của locs không thay đổi.

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