Python có tham chiếu hoặc sao chép không?

Không có câu trả lời nào ở đây cung cấp cho bạn bất kỳ mã nào để làm việc để thực sự minh họa lý do tại sao điều này xảy ra ở vùng đất Python. Và điều này thật thú vị khi xem xét theo cách tiếp cận sâu hơn, vì vậy đây là

Lý do chính khiến điều này không hoạt động như bạn mong đợi là vì trong Python, khi bạn viết

i += 1

nó không làm những gì bạn nghĩ nó đang làm. Số nguyên là bất biến. Điều này có thể được nhìn thấy khi bạn nhìn vào đối tượng thực sự là gì trong Python

a = 0
print['ID of the first integer:', id[a]]
a += 1
print['ID of the first integer +=1:', id[a]]

Hàm id đại diện cho một giá trị duy nhất và không đổi cho một đối tượng trong thời gian tồn tại của nó. Về mặt khái niệm, nó ánh xạ lỏng lẻo tới một địa chỉ bộ nhớ trong C/C++. Chạy đoạn mã trên

ID of the first integer: 140444342529056
ID of the first integer +=1: 140444342529088

Điều này có nghĩa là

a = 0
print['ID of the first integer:', id[a]]
a += 1
print['ID of the first integer +=1:', id[a]]
4 đầu tiên không còn giống với
a = 0
print['ID of the first integer:', id[a]]
a += 1
print['ID of the first integer +=1:', id[a]]
4 thứ hai, vì id của họ khác nhau. Thực tế là chúng ở các vị trí khác nhau trong bộ nhớ

Tuy nhiên, với một đối tượng, mọi thứ hoạt động khác đi. Tôi đã ghi đè toán tử

a = 0
print['ID of the first integer:', id[a]]
a += 1
print['ID of the first integer +=1:', id[a]]
0 tại đây

class CustomInt:
  def __iadd__[self, other]:
    # Override += 1 for this class
    self.value = self.value + other.value
    return self

  def __init__[self, v]:
    self.value = v

ints = []
for i in range[5]:
  int = CustomInt[i]
  print['ID={}, value={}'.format[id[int], i]]
  ints.append[int]


for i in ints:
  i += CustomInt[i.value]

print["######"]
for i in ints:
  print['ID={}, value={}'.format[id[i], i.value]]

Chạy kết quả này trong đầu ra sau

ID=140444284275400, value=0
ID=140444284275120, value=1
ID=140444284275064, value=2
ID=140444284310752, value=3
ID=140444284310864, value=4
######
ID=140444284275400, value=0
ID=140444284275120, value=2
ID=140444284275064, value=4
ID=140444284310752, value=6
ID=140444284310864, value=8

Lưu ý rằng thuộc tính id trong trường hợp này thực sự giống nhau cho cả hai lần lặp, mặc dù giá trị của đối tượng là khác nhau [bạn cũng có thể tìm thấy giá trị _____ của giá trị int mà đối tượng nắm giữ, giá trị này sẽ thay đổi khi nó thay đổi - bởi vì

So sánh điều này với khi bạn chạy cùng một bài tập với một đối tượng bất biến

ints_primitives = []
for i in range[5]:
  int = i
  ints_primitives.append[int]
  print['ID={}, value={}'.format[id[int], i]]

print["######"]
for i in ints_primitives:
  i += 1
  print['ID={}, value={}'.format[id[int], i]]


print["######"]
for i in ints_primitives:
  print['ID={}, value={}'.format[id[i], i]]

kết quả này

________số 8

Một vài điều ở đây cần chú ý. Đầu tiên, trong vòng lặp với

a = 0
print['ID of the first integer:', id[a]]
a += 1
print['ID of the first integer +=1:', id[a]]
0, bạn không còn thêm vào đối tượng ban đầu nữa. Trong trường hợp này, vì ints là một trong những loại bất biến trong Python, nên python sử dụng một id khác. Cũng thú vị khi lưu ý rằng Python sử dụng cùng một
a = 0
print['ID of the first integer:', id[a]]
a += 1
print['ID of the first integer +=1:', id[a]]
1 cơ bản cho nhiều biến có cùng giá trị bất biến

a = 0
print['ID of the first integer:', id[a]]
a += 1
print['ID of the first integer +=1:', id[a]]
1

tl;dr - Python có một số loại bất biến, gây ra hành vi mà bạn thấy. Đối với tất cả các loại có thể thay đổi, kỳ vọng của bạn là chính xác

Khi một chương trình thực hiện một phép gán chẳng hạn như a = b, một tham chiếu mới đến b được tạo. Đối với các đối tượng bất biến như số và chuỗi, phép gán này tạo một bản sao của b một cách hiệu quả. Tuy nhiên, hành vi khá khác đối với các đối tượng có thể thay đổi như danh sách và từ điển. Ví dụ

a = 0
print['ID of the first integer:', id[a]]
a += 1
print['ID of the first integer +=1:', id[a]]
2

Vì a và b tham chiếu đến cùng một đối tượng trong ví dụ này, một thay đổi được thực hiện đối với một trong các biến được phản ánh trong biến kia. Để tránh điều này, bạn phải tạo một bản sao của đối tượng thay vì một tham chiếu mới

Hai loại hoạt động sao chép được áp dụng cho các đối tượng vùng chứa như danh sách và từ điển. một bản sao nông và một bản sao sâu. Một bản sao nông tạo một đối tượng mới, nhưng điền vào nó các tham chiếu đến các mục có trong đối tượng ban đầu. Ví dụ

a = 0
print['ID of the first integer:', id[a]]
a += 1
print['ID of the first integer +=1:', id[a]]
3

Trong trường hợp này, a và b là các đối tượng danh sách riêng biệt, nhưng các phần tử chứa chúng được chia sẻ. Do đó, một sửa đổi đối với một trong các phần tử của a cũng sửa đổi một phần tử của b, như được hiển thị

Một bản sao sâu tạo một đối tượng mới và sao chép đệ quy tất cả các đối tượng mà nó chứa. Không có chức năng tích hợp để tạo bản sao sâu của đối tượng. Tuy nhiên, bản. Có thể sử dụng hàm deepcopy[] trong thư viện chuẩn, như minh họa trong ví dụ sau

Python có sử dụng tài liệu tham khảo không?

Chương trình Python truy cập giá trị dữ liệu thông qua tham chiếu . Tham chiếu là tên đề cập đến vị trí cụ thể trong bộ nhớ của một giá trị [đối tượng]. Tham chiếu có dạng biến, thuộc tính và mục. Trong Python, một biến hoặc tham chiếu khác không có kiểu nội tại.

Python có trả về giá trị hoặc tham chiếu không?

Trong Python, các đối số luôn được truyền theo giá trị và giá trị trả về luôn được trả về theo giá trị . Tuy nhiên, giá trị được trả về [hoặc được chuyển] là một tham chiếu đến một đối tượng có khả năng chia sẻ, có khả năng thay đổi.

Python có vượt qua bản sao không?

Đây không phải là những gì Python làm, Python không sử dụng mô hình truyền theo giá trị. Đây có vẻ giống như mô hình chuyển theo giá trị vì chúng tôi đã cho điểm này là 3, đổi thành 4 và thay đổi không được phản ánh ra bên ngoài [ a vẫn là 3]. Nhưng trên thực tế, Python không sao chép dữ liệu vào hàm .

Là tham chiếu hoặc giá trị gán Python?

Python di chuyển các đối số thông qua phép gán, vì vậy không theo Tham chiếu cũng như theo giá trị . Logic cho điều này là gấp đôi. Hiện tại, tham số truyền vào là một con trỏ tới một đối tượng. Một số loại dữ liệu có thể thay đổi và một số không thể thay đổi.

Chủ Đề