HomeLập trìnhPythonCác đối tượng...

Các đối tượng có thể thay đổi và không thể thay đổi trong Python – Hướng dẫn trực quan và thực hành


Python là một ngôn ngữ tuyệt vời. Vì tính đơn giản của nó, nhiều người chọn nó làm ngôn ngữ lập trình đầu tiên của họ.

Các lập trình viên có kinh nghiệm cũng sử dụng Python mọi lúc nhờ cộng đồng rộng lớn, các gói phong phú và cú pháp rõ ràng.

Nhưng có một vấn đề dường như gây nhầm lẫn cho những người mới bắt đầu cũng như một số nhà phát triển có kinh nghiệm: các đối tượng Python. Cụ thể, sự khác biệt giữa có thể thay đổi bất biến các đối tượng.

Trong bài đăng này, chúng ta sẽ đào sâu kiến ​​thức về các đối tượng Python, tìm hiểu sự khác biệt giữa có thể thay đổi bất biến các đối tượng và xem cách chúng ta có thể sử dụng thông dịch viên để hiểu rõ hơn về cách thức hoạt động của Python.

Chúng tôi sẽ sử dụng các chức năng và từ khóa quan trọng như idisvà chúng ta sẽ hiểu sự khác biệt giữa x == yx is y.

Bạn có cho nó? Bắt đầu nào.

Không giống như các ngôn ngữ lập trình khác, nơi ngôn ngữ hỗ trợ các đối tượng, trong Python thực sự mọi thứ là một đối tượng – bao gồm số nguyên, danh sách và thậm chí cả hàm.

Chúng tôi có thể sử dụng thông dịch viên của chúng tôi để xác minh rằng:

>>> isinstance(1, object)
True

>>> isinstance(False, object)
True

def my_func():
   return "hello"
   
>>> isinstance(my_func, object)
True
Mọi thứ trong Python đều là đối tượng

Python có chức năng tích hợp sẵn, id, trả về địa chỉ của một đối tượng trong bộ nhớ. Ví dụ:

>>> x = 1
>>> id(x)
1470416816
Chức năng id(obj) trả về địa chỉ của obj trong trí nhớ

Ở trên, chúng tôi đã tạo một vật bằng tên của xvà gán cho nó giá trị của 1. Sau đó chúng tôi đã sử dụng id(x) và phát hiện ra rằng đối tượng này được tìm thấy tại địa chỉ 1470416816 trong trí nhớ.

Điều này cho phép chúng tôi kiểm tra những điều thú vị về Python. Giả sử chúng ta tạo hai biến trong Python – một biến có tên là xvà một người có tên là y – và gán cho chúng cùng một giá trị. Ví dụ, ở đây:

>>> x = "I love Python!"
>>> y = "I love Python!"

Chúng ta có thể sử dụng toán tử đẳng thức (==) để xác minh rằng chúng thực sự có cùng giá trị trong mắt Python:

>>> x == y
True

Nhưng đây có phải là cùng một đối tượng trong bộ nhớ không? Về lý thuyết, có thể có hai kịch bản rất khác nhau ở đây.

Theo kịch bản (1)chúng tôi thực sự có hai đối tượng khác nhau, một đối tượng có tên là xvà một tên khác yđiều đó chỉ tình cờ có cùng một giá trị.

Tuy nhiên, cũng có thể xảy ra trường hợp Python thực sự chỉ lưu trữ ở đây một đối tượng, có hai tên tham chiếu đến nó – như thể hiện trong tình huống (2):

hình ảnh-19

Chúng ta có thể sử dụng id chức năng được giới thiệu ở trên để kiểm tra điều này:

>>> x = "I love Python!"
>>> y = "I love Python!"
>>> x == y
True

>>> id(x)
52889984

>>> id(y)
52889384

Vì vậy, như chúng ta có thể thấy, hành vi của Python phù hợp với tình huống (1) được mô tả ở trên. Mặc dù x == y trong ví dụ này (có nghĩa là, xy có giống nhau giá trị), chúng là các đối tượng khác nhau trong bộ nhớ. Điều này là do id(x) != id(y)như chúng ta có thể xác minh rõ ràng:

>>> id(x) == id(y)
False

Có một cách ngắn hơn để so sánh ở trên, đó là sử dụng Python’s is nhà điều hành. Kiểm tra xem x is y cũng giống như kiểm tra id(x) == id(y)có nghĩa là liệu xy là cùng một đối tượng trong bộ nhớ:

>>> x == y
True

>>> id(x) == id(y)
False

>>> x is y
False

Điều này làm sáng tỏ sự khác biệt quan trọng giữa toán tử bình đẳng == và toán tử nhận dạng is.

Như bạn có thể thấy trong ví dụ trên, hoàn toàn có thể có hai tên trong Python (xy) bị ràng buộc với hai đối tượng khác nhau (và do đó, x is yFalse), trong đó hai đối tượng này có cùng giá trị (vì vậy x == yTrue).

Đọc thêm  đối tượng builtin_function_or_method không thể đăng ký được Lỗi Python [SOLVED]

Làm cách nào chúng ta có thể tạo một biến khác trỏ đến cùng một đối tượng x đang trỏ tới? Chúng ta chỉ có thể sử dụng toán tử gán =như vậy:

>>> x = "I love Python!"
>>> z = x

Để xác minh rằng chúng thực sự trỏ đến cùng một đối tượng, chúng ta có thể sử dụng is nhà điều hành:

>>> x is z
True

Tất nhiên, điều này có nghĩa là chúng có cùng địa chỉ trong bộ nhớ, vì chúng ta có thể xác minh rõ ràng bằng cách sử dụng id:

>>> id(x)
54221824

>>> id(z)
54221824

Và, tất nhiên, chúng có cùng giá trị, vì vậy chúng tôi mong đợi x == z trở về True cũng:

>>> x == z
True

Chúng tôi đã nói rằng mọi thứ trong Python đều là đối tượng, nhưng có một sự khác biệt quan trọng giữa các đối tượng. Một số đối tượng là có thể thay đổi trong khi một số là bất biến.

Như tôi đã đề cập trước đây, thực tế này gây nhầm lẫn cho nhiều người mới sử dụng Python, vì vậy chúng tôi sẽ đảm bảo rằng nó rõ ràng.

Đối tượng bất biến trong Python

Đối với một số loại trong Python, một khi chúng tôi đã tạo các phiên bản của các loại đó, chúng sẽ không bao giờ thay đổi. họ đang bất biến.

Ví dụ, int các đối tượng là bất biến trong Python. Điều gì sẽ xảy ra nếu chúng ta cố gắng thay đổi giá trị của một int vật?

>>> x = 24601
>>> x
24601

>>> x = 24602
>>> x
24602

Chà, có vẻ như chúng ta đã thay đổi x thành công. Đây chính xác là nơi nhiều người bị nhầm lẫn. Chính xác những gì đã xảy ra dưới mui xe ở đây? Hãy sử dụng id để điều tra thêm:

>>> x = 24601
>>> x
24601

>>> id(x)
1470416816

>>> x = 24602
>>> x
24602

>>> id(x)
1470416832

Vì vậy, chúng ta có thể thấy rằng bằng cách gán x = 24602chúng tôi đã không thay đổi giá trị của đối tượng đó x đã bị ràng buộc trước đó. Thay vào đó, chúng tôi đã tạo một đối tượng mới và đặt tên x với nó.

Vì vậy sau khi giao 24601 đến x bằng cách sử dụng x = 24601chúng tôi đã có trạng thái sau:

hình ảnh-46

Và sau khi sử dụng x = 24602chúng tôi đã tạo một đối tượng mới và đặt tên x cho đối tượng mới này. Đối tượng khác có giá trị là 24601 không còn có thể truy cập được bởi x (hoặc bất kỳ tên nào khác trong trường hợp này):

hinh-47

Bất cứ khi nào chúng ta gán một giá trị mới cho một tên (trong ví dụ trên – x) được liên kết với một int đối tượng, chúng tôi thực sự thay đổi ràng buộc của tên đó thành một đối tượng khác.

Điều tương tự cũng áp dụng cho tuples, chuỗi (str đối tượng), và boolcũng vậy. Nói cách khác, int (và các loại số khác như float), tuple, boolstr đối tượng là bất biến.

Hãy kiểm tra giả thuyết này. Điều gì xảy ra nếu chúng ta tạo một tuple đối tượng, và sau đó cung cấp cho nó một giá trị khác?

>>> my_tuple = (1, 2, 3)
>>> id(my_tuple)
54263304

>>> my_tuple = (3, 4, 5)
>>> id(my_tuple)
56898184

giống như một int đối tượng, chúng ta có thể thấy rằng nhiệm vụ của chúng ta thực sự đã thay đổi đối tượng mà tên my_tuple là ràng buộc để.

Đọc thêm  Đang tải tệp JSON bằng Python – Cách đọc và phân tích cú pháp JSON

Điều gì xảy ra nếu chúng ta cố gắng thay đổi một trong những tuplecác phần tử?

>>> my_tuple[0] = 'a new value'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment

Như chúng ta có thể thấy, Python không cho phép chúng ta sửa đổi my_tuplenội dung của nó, vì nó là bất biến.

Các đối tượng có thể thay đổi trong Python

Một số loại trong Python có thể được sửa đổi sau khi tạo và chúng được gọi là có thể thay đổi. Ví dụ, chúng tôi biết rằng chúng tôi có thể sửa đổi nội dung của một list vật:

>>> my_list = [1, 2, 3]
>>> my_list[0] = 'a new value'
>>> my_list
['a new value', 2, 3]

Điều đó có nghĩa là chúng ta thực sự đã tạo một đối tượng mới khi gán một giá trị mới cho phần tử đầu tiên của my_list? Một lần nữa, chúng ta có thể sử dụng id để kiểm tra:

>>> my_list = [1, 2, 3]
>>> id(my_list)
55834760

>>> my_list
[1, 2, 3]

>>> my_list[0] = 'a new value'
>>> id(my_list)
55834760

>>> my_list
['a new value', 2, 3]

Vì vậy, nhiệm vụ đầu tiên của chúng tôi my_list = [1, 2, 3] đã tạo một đối tượng trong địa chỉ 55834760với các giá trị của 1, 23:

hinh-22

Sau đó chúng tôi đã sửa đổi phần tử đầu tiên của điều này list đối tượng sử dụng my_list[0] = 'a new value'nghĩa là – mà không cần tạo mới list vật:

hinh-23

Bây giờ, chúng ta hãy tạo hai tên – xycả hai liên kết với nhau list vật. Chúng tôi có thể xác minh rằng bằng cách sử dụng ishoặc bằng cách kiểm tra rõ ràng idS:

>>> x = y = [1, 2]
>>> x is y
True

>>> id(x)
18349096

>>> id(y)
18349096

>>> id(x) == id(y)
True

Điều gì xảy ra bây giờ nếu chúng ta sử dụng x.append(3)? Đó là, nếu chúng ta thêm một phần tử mới (3) cho đối tượng theo tên của x?

Sẽ x bằng cách thay đổi? Sẽ y?

Chà, như chúng ta đã biết, về cơ bản chúng là hai tên của cùng một đối tượng:

hình ảnh-28

Vì đối tượng này đã được thay đổi nên khi kiểm tra tên của nó, chúng ta có thể thấy giá trị mới:

>>> x.append(3)
>>> x
[1, 2, 3]

>>> y
[1, 2, 3]

Lưu ý rằng xy có giống nhau id như trước đây – vì chúng vẫn bị ràng buộc với nhau list vật:

>>> id(x)
18349096

>>> id(y)
18349096
hinh-27

Ngoài ra lists, các loại Python khác có thể thay đổi bao gồm setcát dictS.

từ điển (dict đối tượng) thường được sử dụng trong Python. Xin nhắc lại, chúng tôi định nghĩa chúng như sau:

my_dict = {"name": "Omer", "number_of_pets": 1}

Sau đó, chúng ta có thể truy cập một phần tử cụ thể bằng tên khóa của nó:

>>> my_dict["name"]
'Omer'

Từ điển là có thể thay đổi, vì vậy chúng ta có thể thay đổi nội dung của chúng sau khi tạo. Tại bất kỳ thời điểm nào, một khóa trong từ điển chỉ có thể trỏ đến một phần tử:

>>> my_dict["name"] = "John"
>>> my_dict["name"]
'John'

Thật thú vị khi lưu ý rằng một khóa của từ điển phải là bất biến:

>>> my_dict = {[1,2]: "Hello"}
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'

Tại sao lại như vậy?

Hãy xem xét tình huống giả định sau (lưu ý: đoạn trích bên dưới thực sự không thể chạy được trong Python):

>>> x = [1, 2]
>>> y = [1, 2, 3]
>>> my_dict = {x: 'a', y: 'b'}
Đây là một trường hợp giả định không thể thực sự chạy trong Python

Cho đến nay, mọi thứ dường như không tệ lắm. Chúng tôi cho rằng nếu chúng tôi truy cập my_dict với chìa khóa của [1, 2]ta sẽ nhận được giá trị tương ứng của 'a'và nếu chúng ta truy cập khóa [1, 2, 3]chúng ta sẽ nhận được giá trị 'b'.

Bây giờ, điều gì sẽ xảy ra nếu chúng ta cố gắng sử dụng:

>>> x.append(3)

Trong trường hợp này, x sẽ có giá trị của [1, 2, 3]y cũng sẽ có giá trị của [1, 2, 3]. Chúng ta sẽ nhận được gì khi yêu cầu my_dict[[1, 2, 3]]? Sẽ là như vậy 'a' hoặc 'b'? Để tránh những trường hợp như vậy, Python đơn giản là không cho phép các khóa từ điển có thể thay đổi được.

Đọc thêm  Cách tạo tiền điện tử của riêng bạn bằng Python

Hãy thử áp dụng kiến ​​thức của chúng ta vào một trường hợp thú vị hơn một chút.

Dưới đây, chúng tôi định nghĩa một list (một có thể thay đổi đối tượng) và một tuple (một bất biến vật). Các list Bao gồm một tupletuple Bao gồm một list:

>>> my_list = [(1, 1), 2, 3]
>>> my_tuple = ([1, 1], 2, 3)
>>> type(my_list)
<class 'list'>

>>> type(my_list[0])
<class 'tuple'>

>>> type(my_tuple)
<class 'tuple'>

>>> type(my_tuple[0])
<class 'list'>

Càng xa càng tốt. Bây giờ, hãy thử tự suy nghĩ – điều gì sẽ xảy ra khi chúng ta cố gắng thực hiện từng câu lệnh sau đây?

(1) >>> my_list[0][0] = 'Changed!'

(2) >>> my_tuple[0][0] = 'Changed!'

Trong tuyên bố (1), những gì chúng tôi đang cố gắng làm là thay đổi my_listphần tử đầu tiên của ‘, đó là, một tuple. Từ một tuplebất biếnnỗ lực này chắc chắn sẽ thất bại:

>>> my_list[0][0] = 'Changed!'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment

Lưu ý rằng những gì chúng tôi đã cố gắng làm là không phải thay đổi danh sách, mà thay vào đó – thay đổi nội dung của phần tử đầu tiên.

Hãy xem xét tuyên bố (2). Trong trường hợp này, chúng tôi đang truy cập my_tupleyếu tố đầu tiên của, đó là một list, và sửa đổi nó. Hãy điều tra thêm trường hợp này và xem địa chỉ của các phần tử này:

>>> my_tuple = ([1, 1], 2, 3)
>>> id(my_tuple)
20551816

>>> type(my_tuple[0])
<class 'list'>

>>> id(my_tuple[0])
20446248
hình ảnh-29

Khi chúng ta thay đổi my_tuple[0][0]chúng tôi không thực sự thay đổi my_tuple ở tất cả! Thật vậy, sau khi thay đổi, my_tuplephần tử đầu tiên của vẫn sẽ là đối tượng có địa chỉ trong bộ nhớ là 20446248. Tuy nhiên, chúng tôi thay đổi giá trị của đối tượng đó:

>>> my_tuple[0][0] = 'Changed!'
>>> id(my_tuple)
20551816

>>> id(my_tuple[0])
20446248

>>> my_tuple
(['Changed!', 1], 2, 3)
Cả hai id(my_tuple)id(my_tuple[0]) giữ nguyên sau khi thay đổi
hình ảnh-48

Vì chúng tôi chỉ sửa đổi giá trị của my_tuple[0]đó là một đột biến list đối tượng, thao tác này thực sự đã được Python cho phép.

Trong bài đăng này, chúng ta đã tìm hiểu về các đối tượng Python. Chúng tôi đã nói rằng trong Python tất cả mọi thứ là một đối tượngvà phải sử dụng idis để hiểu sâu hơn về những gì đang diễn ra bên trong khi sử dụng Python để tạo và sửa đổi các đối tượng.

Chúng tôi cũng đã học được sự khác biệt giữa có thể thay đổi các đối tượng, có thể được sửa đổi sau khi tạo và bất biến đối tượng, mà không thể.

Chúng tôi đã thấy rằng khi chúng tôi yêu cầu Python sửa đổi một đối tượng bất biến được liên kết với một tên nhất định, chúng tôi thực sự tạo một đối tượng mới và liên kết tên đó với nó.

Sau đó, chúng tôi đã tìm hiểu lý do tại sao các khóa từ điển phải được bất biến trong Python.

Hiểu cách Python “nhìn thấy” các đối tượng là chìa khóa để trở thành một lập trình viên Python giỏi hơn. Tôi hy vọng bài đăng này đã giúp bạn trên hành trình thành thạo Python.

Omer Rosenbaum, bơiGiám đốc Công nghệ của. Chuyên gia đào tạo mạng và Người sáng lập Học viện An ninh Checkpoint. Tác giả của Mạng máy tính (bằng tiếng Do Thái). Ghé thăm tôi Kênh Youtube.



Zik.vn – Biên dịch & Biên soạn Lại

spot_img

Create a website from scratch

Just drag and drop elements in a page to get started with Newspaper Theme.

Buy Now ⟶

Bài viết liên quang

DMCA.com Protection Status