Chuỗi python có thể thay đổi

Gần đây tôi đã có một trải nghiệm thú vị mà hóa ra lại là một bài học tuyệt vời về khả năng thay đổi của các đối tượng, đặc biệt là các chuỗi, trong Python. Trải nghiệm này là kết quả của việc làm rối tung hai bộ não Python, cảm thấy khó chịu về một sự mâu thuẫn có vẻ mâu thuẫn trong chức năng ngôn ngữ, và sau đó đi xuống một hố thỏ hấp dẫn

Brainteaser đầu tiên, lịch sự của Mike Driscoll trên Twitter là

i = j = [3]i += jprint[i, j]

Chương trình sẽ xuất ra cái gì?

Điều này có vẻ như là một điều khá dễ dàng. Các biến và ij đều được chỉ định trỏ vào một danh sách chứa số 3. Tiếp theo, biến i được sửa đổi tại chỗ bằng cách thêm biến j vào nó

Đối với danh sách, toán tử cộng trong Python nối nội dung mới của danh sách thứ hai vào nội dung của danh sách đầu tiên, vì vậy bây giờ là i == [3, 3], trong khi j vẫn là

x = y = “Python”x += “rocks!”print[x, y]
0 vì nó không được sửa đổi, vì vậy việc in i, j sẽ in ra i [ . Vì vậy, câu trả lời cuối cùng phải là
x = y = “Python”x += “rocks!”print[x, y]
7

Những người quen thuộc với cách Python triển khai các biến dưới dạng con trỏ sẽ nhận ra lỗi của tôi. ij đều trỏ đến cùng một đối tượng trong bộ nhớ, vì vậy mặc dù i là đối tượng duy nhất được sửa đổi rõ ràng, nhưng khi đối tượng trong bộ nhớ thay đổi, thì giá trị của j cũng vậy. Vì vậy, câu trả lời đúng là

a = “Hello”id[a]140214243255728a += “!”id[a]
2

Ok, rút ​​kinh nghiệm. Vì vậy, khi một ý tưởng khác, trông rất giống, xuất hiện trong nguồn cấp dữ liệu tin tức của tôi [một lần nữa với sự giúp đỡ của Mike Driscoll], tôi nghĩ rằng mình sẽ hiểu đúng.

x = y = “Python”x += “rocks!”print[x, y]

Chương trình sẽ xuất ra cái gì?’’’

Trông gần giống với vấn đề trước đó, phải không? . Do đó,

a = “Hello”id[a]140214243255728a += “!”id[a]
3 sẽ trở thành
a = “Hello”id[a]140214243255728a += “!”id[a]
4. Và, như tôi đã học được từ brainteaser trước đó, vì
a = “Hello”id[a]140214243255728a += “!”id[a]
3 và
a = “Hello”id[a]140214243255728a += “!”id[a]
6 trỏ đến cùng một đối tượng trong bộ nhớ, nên
a = “Hello”id[a]140214243255728a += “!”id[a]
6 cũng sẽ bị biến đổi thành
a = “Hello”id[a]140214243255728a += “!”id[a]
4 phải không?

Sai. Bất kỳ người hâm mộ Python nào cũng sẽ nói với bạn rằng các chuỗi Python là “bất biến”, nghĩa là chúng không thể được sửa đổi trực tiếp. Thay vào đó, khi bạn cố gắng sửa đổi một chuỗi, Python sẽ tạo một đối tượng mới trong bộ nhớ dựa trên đột biến mà bạn muốn áp dụng cho đối tượng ban đầu. Vì vậy, trong khi

a = “Hello”id[a]140214243255728a += “!”id[a]
3 biến thành
a = “Hello”id[a]140214243255728a += “!”id[a]
4, thì
a = “Hello”id[a]140214243255728a += “!”id[a]
6 vẫn là i2, vì vậy in chúng cạnh nhau sẽ cho bạn i3

Khỏe. Khó chịu, nhưng đủ đơn giản. Tuy nhiên, trong nghiên cứu của tôi về khả năng biến đổi của chuỗi trong Python, tôi đã tìm thấy một ví dụ khác [được sửa đổi để dễ đọc, lần này là từ Austin Henley] dường như mâu thuẫn với những gì tôi vừa học

a = “Hello”id[a]140214243255728a += “!”id[a]

Bây giờ, vì chúng ta vừa cố gắng thay đổi một chuỗi bất biến, nên sẽ có một đối tượng mới trong bộ nhớ mã hóa i4 tại một vị trí mới trong bộ nhớ. Do đó, việc gọi i5 của biến i6 sẽ in ra một địa chỉ bộ nhớ khác với địa chỉ mà chúng ta đã thấy trước đây, phải không?

SAI MỘT LẦN NỮA. Và điều này thực sự đã ném tôi cho một vòng lặp. Tôi đã phải vật lộn để xử lý tính bất biến của các chuỗi, vì vậy bây giờ biết rằng rõ ràng chúng có thể thay đổi khiến tôi mất niềm tin vào bản chất tất định của máy tính. Làm thế quái nào mà cả ví dụ này và ví dụ trước đều đúng?

Những độc giả chú ý nhiều đến chi tiết hoặc đặc biệt là Python-adroit có thể nhận thấy sự khác biệt giữa ví dụ thứ hai và thứ ba. Trong ví dụ thứ hai, hai biến trỏ đến cùng một đối tượng trong bộ nhớ, trong khi ở ví dụ thứ ba, chỉ một biến duy nhất trỏ đến đối tượng. Tại sao nó quan trọng? . Nếu không có tham chiếu nào khác đến chuỗi, thì nó sẽ cố gắng thay đổi chuỗi thay vì cấp phát một chuỗi mới” [nhấn mạnh của tôi]. Trong trường hợp brainteaser hai, cả

a = “Hello”id[a]140214243255728a += “!”id[a]
3 và
a = “Hello”id[a]140214243255728a += “!”id[a]
6 đều chỉ vào cùng một đối tượng trong bộ nhớ, do đó, tính bất biến được bảo toàn

Thông minh thực sự. Hoặc chỉ bực bội khủng khiếp. Bởi vì, như Henley tiếp tục chỉ ra rằng ngay cả lời giải thích này cũng hơi đơn giản hóa. Nếu đột biến trên chuỗi ban đầu phát triển quá lớn, đôi khi CPython sẽ thay đổi kích thước bộ đệm, tạo một đối tượng mới trong bộ nhớ và do đó giữ lại hình ảnh “bất biến”. Khi chạy một điểm chuẩn, anh ấy thấy rằng việc thay đổi kích thước bộ đệm khiến địa chỉ trong bộ nhớ thay đổi 46 lần trong số 10.000

Và, lập luận với người bạn của tôi, người mà tôi đã thảo luận về vấn đề này, ngay cả khi chúng tôi bỏ qua trường hợp thay đổi kích thước bộ đệm, đây có phải là hành vi nguy hiểm không?

Sau khi suy nghĩ về điều này nhiều hơn một chút, chúng tôi nhận ra rằng, mặc dù kỳ quặc nhưng hành vi này không thực sự nguy hiểm. Rốt cuộc, các lập trình viên có thể tránh giả định rằng một đối tượng bị đột biến sẽ giữ lại địa chỉ của nó trong bộ nhớ. Nếu hai hoặc nhiều biến trỏ đến cùng một đối tượng, thì sự đột biến được đảm bảo dẫn đến một địa chỉ mới cho đối tượng được trỏ đến bởi biến đã sửa đổi. Nếu một số lượng biến không xác định trỏ đến cùng một đối tượng, bạn có thể cho rằng nó sẽ nhận một địa chỉ mới trong bộ nhớ, nhưng nếu “địa chỉ mới” đó trùng với địa chỉ cũ, thì đó không phải là vấn đề

Nhìn chung, đây là một cách cực kỳ khó khăn để thấm sâu vào đầu tôi khả năng xử lý con trỏ trong Python và khả năng biến đổi. Đây là hy vọng nó dính

Tại sao một chuỗi không thay đổi trong Python?

Trong Python, các chuỗi được tạo thành bất biến để lập trình viên không thể thay đổi nội dung của đối tượng [thậm chí do nhầm lẫn]. Điều này tránh các lỗi không cần thiết. Một số đối tượng bất biến khác là số nguyên, float, tuple và bool. Tìm hiểu thêm về các đối tượng có thể thay đổi và không thể thay đổi trong Python.

Chuỗi có thể thay đổi hay không thay đổi?

Chuỗi là một ví dụ về loại bất biến .

Tại sao chuỗi không phải là bất biến trong Python?

Trong python, kiểu dữ liệu chuỗi là bất biến. Điều đó có nghĩa là không thể cập nhật giá trị chuỗi . Chúng tôi có thể xác minh điều này bằng cách thử cập nhật một phần của chuỗi sẽ dẫn đến lỗi. Chúng tôi có thể xác minh thêm điều này bằng cách kiểm tra địa chỉ vị trí bộ nhớ của vị trí của các chữ cái trong chuỗi.

Các chuỗi có bất biến trong ví dụ về Python không?

Đối tượng bất biến . Một đối tượng chuỗi sẽ luôn đại diện cho cùng một giá trị, không thể sửa đổi nó. Ví dụ — Đối tượng chuỗi 'h' sẽ luôn đại diện cho giá trị python h .

Chủ Đề