2012-06-27 43 views
33

Trong mãgán biến tham chiếu Python

y = 7 
x = y  
x = 8 

Bây giờ, y sẽ là 7 và x sẽ là 8. Tuy nhiên, thực sự tôi muốn thay đổi y. Tôi có thể chỉ định tham chiếu y và làm điều đó không?

Ví dụ, trong C++ được điều tương tự có thể đạt được như,

int y = 8; 
int &x = y; 
x = 9; 

Bây giờ cả hai y & x sẽ là 9

Trả lời

44

Không, bạn không thể. Như câu trả lời khác chỉ ra, bạn có thể (ab?) Sử dụng bí danh của các đối tượng có thể thay đổi để đạt được một hiệu ứng tương tự. Tuy nhiên, đó không phải là điều tương tự như tài liệu tham khảo C++, và tôi muốn giải thích những gì thực sự xảy ra để tránh bất kỳ quan niệm sai lầm nào.

Bạn thấy, trong C++ (và các ngôn ngữ khác), biến (và trường đối tượng và mục nhập trong bộ sưu tập, v.v.) là vị trí lưu trữ và bạn viết giá trị (ví dụ: số nguyên, đối tượng hoặc một con trỏ) đến vị trí đó. Trong mô hình này, tham chiếu là bí danh cho vị trí lưu trữ (bất kỳ loại nào) - khi bạn gán cho biến không tham chiếu, bạn sao chép giá trị (ngay cả khi nó chỉ là con trỏ, nó vẫn là giá trị) cho vị trí lưu trữ; khi bạn gán cho một tham chiếu, bạn sao chép vào một vị trí lưu trữ ở một nơi khác. Lưu ý rằng bạn không thể thay đổi một tham chiếu - một khi nó bị ràng buộc (và nó phải ngay sau khi bạn tạo một) tất cả các nhiệm vụ cho nó thay đổi không phải là tham chiếu nhưng bất cứ điều gì được nhắc tới.

Trong Python (và các ngôn ngữ khác), một biến (và trường đối tượng và mục nhập trong bộ sưu tập, v.v.) chỉ là một tên. Giá trị là ở đâu đó khác (ví dụ: rắc khắp đống) và biến tham chiếu (không theo nghĩa của tham chiếu C++, giống như con trỏ trừ số học con trỏ) thành giá trị. Nhiều tên có thể tham chiếu đến cùng một giá trị (thường là một điều tốt). Python (và các ngôn ngữ khác) gọi bất cứ điều gì là cần thiết để tham chiếu đến một giá trị một tham chiếu, mặc dù là khá không liên quan đến những thứ như C++ tài liệu tham khảo và pass-by-tham khảo. Chỉ định cho một biến (hoặc trường đối tượng, hoặc ...) đơn giản chỉ làm cho nó tham chiếu đến một giá trị khác.Toàn bộ mô hình vị trí lưu trữ không áp dụng cho Python, lập trình viên không bao giờ xử lý các vị trí lưu trữ cho các giá trị. Tất cả các cửa hàng và shuffles xung quanh là tài liệu tham khảo Python, và những người không phải là giá trị trong Python, vì vậy họ không thể được nhắm mục tiêu của tài liệu tham khảo Python khác.

Tất cả điều này là độc lập với tính đột biến của giá trị - ví dụ như đối với int và danh sách. Bạn không thể lấy một biến đề cập đến một trong hai, và ghi đè lên đối tượng nó trỏ đến. Bạn chỉ có thể yêu cầu đối tượng sửa đổi các phần của chính nó - giả sử thay đổi một số tham chiếu chứa nó.

Đây có phải là mô hình hạn chế hơn không? Có lẽ, nhưng nó đủ mạnh hầu hết thời gian. Và khi nó không phải là bạn có thể làm việc xung quanh nó, hoặc với một lớp tùy chỉnh giống như một lớp dưới đây, hoặc (tương đương, nhưng ít rõ ràng hơn) một bộ sưu tập phần tử đơn.

class Reference: 
    def __init__(self, val): 
     self._value = val # just refers to val, no copy 

    def get(self): 
     return self._value 

    def set(self, val): 
     self._value = val 

Đó vẫn sẽ không cho phép bạn bí danh là "thường xuyên" lĩnh vực biến hoặc đối tượng, nhưng bạn có thể có nhiều biến đề cập đến cùng một đối tượng Reference (như trên cho giải pháp thay thế có thể thay đổi-singleton thu). Bạn chỉ cần cẩn thận để luôn sử dụng .get()/.set() (hoặc [0]).

+2

Giải thích tốt, +1 để làm rõ rằng nó không liên quan gì đến tính đột biến. –

11

Không, Python không có tính năng này.

Nếu bạn đã có một danh sách (hoặc bất kỳ đối tượng có thể thay đổi khác), bạn có thể làm những gì bạn muốn bằng cách biến đổi các đối tượng mà cả x và y đang bị ràng buộc để:

>>> x = [7] 
>>> y = x 
>>> y[0] = 8 
>>> print x 
[8] 

Xem nó làm việc trực tuyến: ideone

+1

Mặc dù điều này thực sự hữu ích nhưng có nhiều nhược điểm lớn hơn trong "đột biến" này của một giá trị số đơn giản. Quay số nguyên trong danh sách với một phần tử đơn yêu cầu ít hơn 3 lần dung lượng bộ nhớ bạn thường cần. Ví dụ (tôi sẽ sử dụng sys.getsizeof (...) để minh họa sự khác biệt về kích thước): x = 1 -> sys.getsizeof (x) -> cung cấp cho chúng tôi 14 -> x = [1] -> sys.getsizeof (x) -> cho chúng ta 36 – rbaleksandar

5

Bạn nên sử dụng đối tượng có thể thay đổi cho điều này.

Trong python x & y chỉ là tài liệu tham khảo cho các đối tượng nên y = 7 nghĩa điểm y đến đối tượng 7. x=y có nghĩa là x quá điểm đến 7, nhưng như 7 là không thay đổi để thay đổi giá trị của x chỉ cần thay đổi đối tượng 7y vẫn trỏ đến 7.

>>> y = [7] 
>>> x = y 
>>> x[0] = 8 # here you're changing [7] not x or y, x & y are just references to [7] 
>>> y 
[8] 
+0

bạn muốn chỉ ra rằng y vẫn không thay đổi ngay cả sau khi thay đổi x, nhưng đó không phải là những gì bạn đã viết ở đây. Vui lòng làm rõ. –

1

Hoặc, bạn có thể sử dụng vùng chứa tự chế tác.

class Value(object): 
    def __init__(self, value): self.value = value 

y = Value(7) 
x = y 
x.value = 8 
print y.value 

ideone

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