× Giới thiệu Lịch khai giảng Tin tức Sản phẩm học viên

Python's Mutable vs Immutable Types: Sự khác biệt là gì?

10/03/2023 01:22

Python's Mutable vs Immutable Types rất quan trọng trong lập trình Python. Do đó, bạn cần biết cách các đối tượng này hoạt động trong quá trình làm dự án

Là một nhà phát triển Python, sớm hay muộn bạn cũng sẽ phải xử lý các đối tượng có thể thay đổi và không thể thay đổi . Các đối tượng có thể thay đổi là những đối tượng cho phép bạn thay đổi giá trị hoặc dữ liệu của chúng tại chỗ mà không ảnh hưởng đến danh tính của đối tượng. Ngược lại, các đối tượng bất biến không cho phép loại hoạt động này. Bạn sẽ chỉ có tùy chọn tạo các đối tượng mới cùng loại với các giá trị khác nhau.

Trong Python, khả năng thay đổi là một đặc điểm có thể ảnh hưởng sâu sắc đến quyết định của bạn khi chọn loại dữ liệu nào sẽ sử dụng để giải quyết một vấn đề lập trình nhất định. Do đó, bạn cần biết cách các đối tượng có thể thay đổi và không thể thay đổi hoạt động trong Python.

Trong hướng dẫn này, bạn sẽ:

  • Hiểu cách thức hoạt động của tính biến đổi và tính không thay đổi trong Python
  • Khám phá các kiểu dữ liệu tích hợp bất biến và có thể thay đổi trong Python
  • Xác định và tránh một số vấn đề phổ biến liên quan đến khả năng biến đổi
  • Hiểu và kiểm soát khả năng biến đổi ảnh hưởng đến các lớp tùy chỉnh của bạn như thế nào

Tính đột biến vs tính bất biến

Trong lập trình, bạn có một đối tượng bất biến nếu bạn không thể thay đổi trạng thái của đối tượng sau khi đã tạo. Ngược lại, một đối tượng có thể thay đổi cho phép bạn sửa đổi trạng thái bên trong của nó sau khi tạo. Tóm lại, việc bạn có thể thay đổi trạng thái của đối tượng hoặc dữ liệu chứa trong đó hay không là điều xác định xem đối tượng đó có thể thay đổi hay không thay đổi.

Các đối tượng bất biến thường phổ biến trong lập trình hàm , trong khi các đối tượng có thể thay đổi được sử dụng rộng rãi trong lập trình hướng đối tượng . Bởi vì Python là ngôn ngữ lập trình đa mô hình, nó cung cấp các đối tượng có thể thay đổi và không thể thay đổi để bạn lựa chọn khi giải quyết vấn đề.

Để hiểu cách hoạt động của các đối tượng có thể thay đổi và bất biến trong Python, trước tiên bạn cần hiểu một số khái niệm liên quan. Để bắt đầu, bạn sẽ xem xét các biến và đối tượng.

Biến và đối tượng

Trong Python, các biến không có loại hoặc kích thước liên quan, vì chúng là các nhãn được gắn vào các đối tượng trong bộ nhớ. Chúng trỏ đến vị trí bộ nhớ nơi các đối tượng cụ thể sống. Nói cách khác, một biến Python là một tên đề cập đến hoặc giữ một tham chiếu đến một đối tượng cụ thể. Ngược lại, các đối tượng Python là những mẩu thông tin cụ thể nằm trong các vị trí bộ nhớ cụ thể trên máy tính của bạn.

Điểm chính ở đây là các biến và đối tượng là hai động vật khác nhau trong Python:

  • Các biến giữ tham chiếu đến các đối tượng.
  • Các đối tượng sống trong các vị trí bộ nhớ cụ thể.

Cả hai khái niệm đều độc lập với nhau. Tuy nhiên, chúng có liên quan chặt chẽ với nhau. Khi bạn đã tạo một biến với câu lệnh gán , thì bạn có thể truy cập đối tượng được tham chiếu trong toàn bộ mã của mình bằng cách sử dụng tên biến. Nếu đối tượng được tham chiếu có thể thay đổi, thì bạn cũng có thể thực hiện các thay đổi trên nó thông qua biến. Tính có thể thay đổi hoặc tính không thay đổi là nội tại đối với các đối tượng hơn là đối với các biến.

Tuy nhiên, nếu đối tượng được tham chiếu là bất biến, thì bạn sẽ không thể thay đổi trạng thái bên trong của nó hoặc dữ liệu chứa trong đó. Bạn sẽ chỉ có thể biến tham chiếu biến của mình thành một đối tượng khác, trong Python, có thể cùng loại hoặc không cùng loại với đối tượng ban đầu của bạn.

Nếu bạn không có tham chiếu (biến) cho một đối tượng thì bạn không thể truy cập đối tượng đó trong mã của mình. Nếu bạn làm mất hoặc xóa tất cả các tham chiếu đến một đối tượng nhất định, thì Python sẽ thu gom rác đối tượng đó, giải phóng bộ nhớ để sử dụng sau.

Bây giờ bạn đã biết rằng có sự khác biệt giữa các biến và đối tượng, bạn cần biết rằng tất cả các đối tượng Python đều có ba thuộc tính cốt lõi: danh tính, loại và giá trị.

Đối tượng, Giá trị, Danh tính và Loại

Trong Python, mọi thứ đều là đối tượng. Ví dụ: số , chuỗi , hàm , lớp và mô-đun đều là các đối tượng. Mỗi đối tượng Python có ba đặc điểm cốt lõi xác định nó ở cấp độ cơ bản. Những đặc điểm này là:

  1. Giá trị
  2. Danh tính
  3. Kiểu

Có thể cho rằng, giá trị có lẽ là đặc điểm đối tượng quen thuộc nhất mà bạn đã xử lý. Giá trị của một đối tượng bao gồm phần cụ thể hoặc các phần dữ liệu chứa trong chính đối tượng đó. Một ví dụ cổ điển là một giá trị số như số nguyên hoặc số dấu phẩy động :

>>>
>>> 42
42
>>> isinstance(42, int)
True

>>> 3.14
3.14
>>> isinstance(3.14, float)
True

Các giá trị số này 42và 3.14, đều là đối tượng. Số đầu tiên là một thể hiện của lớp dựng sẵn int, trong khi số thứ hai là một thể hiện của float. Trong cả hai ví dụ, bạn xác nhận loại đối tượng bằng isinstance()hàm tích hợp sẵn.

Python cũng hỗ trợ các đối tượng với các giá trị phức tạp hơn chứa nhiều điểm dữ liệu. Ví dụ: bạn có thể có một danh sách các số như sau:

>>>
>>> [1, 2, 3]
[1, 2, 3]
>>> isinstance([1, 2, 3], list)
True

Trong trường hợp này, bạn có một thể hiện của lớp dựng sẵn listvà giá trị của nó là [1, 2, 3]. Tất nhiên, các ví dụ trong phần này chỉ là một mẫu trong vô số giá trị và dữ liệu mà các đối tượng Python có thể lưu trữ. Điều đó đặc biệt đúng nếu bạn cho rằng bạn cũng có thể tạo các lớp và đối tượng của riêng mình trong Python.

Giá trị của một đối tượng tồn tại ở một vị trí hoặc địa chỉ cụ thể trong bộ nhớ máy tính của bạn. Trong triển khai CPython của Python, địa chỉ bộ nhớ cụ thể này là thứ bạn sẽ biết dưới dạng danh tính của đối tượng . Danh tính này là một mã định danh duy nhất để phân biệt một đối tượng với những đối tượng khác.

Danh tính của đối tượng là thuộc tính chỉ đọc, nghĩa là bạn không thể thay đổi danh tính của đối tượng sau khi đối tượng đã được tạo.

Bạn có thể sử dụng chức năng tích hợp sẵn id()để lấy danh tính của đối tượng:

>>>
>>> id(42)
4343440904

>>> id(3.14)
4376764112

>>> id([1, 2, 3])
4399577728

Nếu bạn gọi id()với một đối tượng nhất định, thì bạn sẽ nhận được một số đóng vai trò là danh tính của đối tượng. Một lần nữa, trong CPython, con số này đại diện cho địa chỉ bộ nhớ nơi đối tượng nằm trong máy tính của bạn. Tuy nhiên, trong các triển khai Python khác , số này có thể có nguồn gốc khác.

Trước khi chuyển sang đặc điểm thứ ba của các đối tượng Python, hãy dành một phút để nghĩ về danh tính của đối tượng. Nó có nhắc bạn về điều gì đó bạn đã học được một lúc trước không? Có, bạn cũng có thể truy cập danh tính của một đối tượng thông qua một biến trỏ đến đối tượng đó:

>>>
>>> number = 42
>>> id(number)
4343440904

Trong ví dụ này, biến trỏ numberđến một đối tượng số nguyên có giá trị là 42. Từ thời điểm này trở đi, bạn có thể truy cập đối tượng, 42, thông qua biến, number.

Đặc điểm cuối cùng của mọi đối tượng Python là kiểu của nó . Loại của một đối tượng xác định đối tượng đó bắt nguồn từ lớp nào. Bạn có thể sử dụng chức năng tích hợp sẵn type()để tìm hiểu về loại đối tượng:

>>>
>>> type(42)
<class 'int'>

>>> type("Hello, World!")
<class 'str'>

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

Ở đây, bạn đã gọi type()với ba đối tượng khác nhau. Đối tượng đầu tiên bắt nguồn từ intlớp, intkiểu của nó cũng vậy. Đối tượng thứ hai là một chuỗi, vì vậy kiểu của nó là str. Cuối cùng, bạn có một đối tượng kiểu list.

Kiểu của một đối tượng xác định các thao tác mà bạn có thể thực hiện với hoặc trên đối tượng đó. Nó cũng xác định các giá trị được chấp nhận. Ví dụ: bạn có thể thực hiện các phép toán số học với các số:

>>>
>>> 5 + 2
7

>>> 10 - 5
5

>>> 21 * 2
42

>>> 15 / 3
5

Như mong đợi, các số hỗ trợ bốn phép toán số học cơ bản và nhiều phép toán khác, chẳng hạn như lũy thừa, modulo, căn bậc hai và giá trị tuyệt đối. Họ cũng hỗ trợ các hoạt động khác, chẳng hạn như so sánh.

Tương tự, các loại đối tượng khác hỗ trợ các loại hoạt động khác. Ví dụ: listcác đối tượng cho phép bạn xác định số lượng mục của chúng bằng hàm len():

>>>
>>> len([1, 2, 3])
3

Trong ví dụ này, bạn sử dụng hàm tích hợp sẵn len()để lấy số mục có trong một đối tượng danh sách. Trong trường hợp này, danh sách đầu vào có ba giá trị trong đó. Bây giờ hãy lưu ý cách bạn không thể sử dụng len()với một số:

>>>
>>> len(42)
Traceback (most recent call last):
    ...
TypeError: object of type 'int' has no len()

Nếu bạn gọi len()với một số làm đối số, thì bạn sẽ nhận được một TypeErrorvì các loại số không hỗ trợ thao tác cụ thể này.

Khi nói đến các đối tượng có thể thay đổi và không thể thay đổi, loại đối tượng là rất quan trọng. Cuối cùng, chính kiểu của đối tượng sẽ xác định các thao tác mà bạn có thể thực hiện trên đối tượng đó. Nếu loại hỗ trợ các đột biến, thì bạn sẽ có các đối tượng dẫn xuất có thể thay đổi. Nếu không, bạn sẽ có các đối tượng dẫn xuất bất biến.

Bây giờ bạn đã biết một vài điều về các đối tượng Python, đã đến lúc bạn đi sâu vào chủ đề cốt lõi của hướng dẫn này: các đối tượng có thể thay đổi và không thể thay đổi trong Python .\

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

Trong Python, danh tính của một đối tượng là đặc điểm chỉ đọc duy nhất. Bạn sẽ đặt nó khi bạn tạo đối tượng lần đầu tiên. Loại đối tượng thường cố định nhưng không chỉ đọc. Bạn có thể thay đổi loại đối tượng bằng cách gán lại .__class__thuộc tính lớp của nó cho một lớp khác:

>>>
>>> class Person:
...     def __init__(self, name):
...         self.name = name
...

>>> class Student(Person):
...     def __init__(self, name, major):
...         super().__init__(name)
...         self.major = major
...

>>> john = Student("John", "Computer Science")
>>> type(john)
<class '__main__.Student'>

>>> john.__class__ = Person
>>> type(john)
<class '__main__.Person'>

>>> john.name
John
>>> john.major
Computer Science

Trong ví dụ này, bạn tạo hai lớp. Studentkế thừa Personvà mở rộng nó với một thuộc tính bổ sung, .major. Sau đó, bạn tạo một thể hiện của Studentvới các đối số thích hợp. Cuối cùng, bạn gán lại thuộc tính của đối tượng .__class__để trỏ đến Personlớp. Lưu ý rằng thay đổi này sửa đổi loại đối tượng nhưng không sửa đổi các thuộc tính hiện tại của đối tượng.

Giá trị của một đối tượng có lẽ là đặc điểm duy nhất mà bạn muốn thay đổi trong mã của mình. Một đối tượng cho phép bạn thay đổi giá trị của nó mà không thay đổi danh tính của nó là một đối tượng có thể thay đổi . Những thay đổi mà bạn có thể thực hiện trên giá trị của đối tượng có thể thay đổi được gọi là các đột biến .

Ngược lại, một đối tượng không cho phép thay đổi giá trị của nó là một đối tượng bất biến . Bạn không có cách nào để thực hiện các thay đổi trên loại đối tượng này. Bạn chỉ có tùy chọn tạo một đối tượng mới cùng loại nhưng có giá trị khác, bạn có thể thực hiện việc này thông qua một nhiệm vụ mới.

Trong Python, bạn sẽ có một số kiểu dựng sẵn theo ý của mình. Hầu hết trong số chúng là bất biến, và một số ít có thể thay đổi. Các kiểu dữ liệu một mục, chẳng hạn như số nguyên, số float, số phức và Booleans , luôn không thay đổi. Vì vậy, bạn không có cách nào để thay đổi giá trị của các loại này. Bạn chỉ có tùy chọn tạo đối tượng mới với giá trị mới và loại bỏ đối tượng cũ.

Khi nói đến các loại bộ sưu tập hoặc vùng chứa , chẳng hạn như chuỗi, danh sách, bộ dữ liệu, bộ và từ điển, mọi thứ sẽ khác một chút. Giống như tất cả các đối tượng khác, một bộ sưu tập có một danh tính duy nhất. Tuy nhiên, các bộ sưu tập bên trong giữ các tham chiếu đến tất cả các giá trị riêng lẻ của chúng. Điều này mở ra cơ hội cho khả năng biến đổi.

Theo định nghĩa của một đối tượng có thể thay đổi, nếu bạn có thể thay đổi giá trị của đối tượng đó mà không thay đổi danh tính của đối tượng, thì bạn có một đối tượng có thể thay đổi. Trong một loại bộ sưu tập, bạn có danh tính của bộ sưu tập và có thể có một số danh tính vật phẩm. Bạn có thể sửa đổi giá trị—và do đó, cả danh tính—của một số mục này trong khi không thay đổi danh tính của bộ sưu tập. Trong trường hợp đó, bạn có một bộ sưu tập có thể thay đổi.

Python có cả kiểu dữ liệu bộ sưu tập có thể thay đổi và không thể thay đổi. Chuỗi và bộ dữ liệu là bất biến, trong khi danh sách, từ điển và bộ có thể thay đổi. Sự khác biệt này rất quan trọng đối với bạn với tư cách là nhà phát triển Python. Bạn sẽ khám phá nó chi tiết hơn sau trong hướng dẫn này. Trước đó, bạn sẽ tìm hiểu về một số sự thật mà bạn nên ghi nhớ khi làm việc với các đối tượng có thể thay đổi và không thể thay đổi.

Cân nhắc khi làm việc với các đối tượng có thể thay đổi và không thể thay đổi

Khi làm việc với các kiểu dữ liệu có thể thay đổi và không thể thay đổi trong Python, bạn phải xem xét việc sử dụng một hoặc một loại đối tượng khác sẽ ảnh hưởng đến mã của bạn như thế nào.

Đầu tiên, để làm việc với các đối tượng bất biến, bạn có thể cần nhiều bộ nhớ hơn vì bạn không thể thay đổi dữ liệu trực tiếp trong chính đối tượng đó. Thay vào đó, bạn cần tạo các đối tượng mới, điều này có thể dẫn đến nhiều bản sao khác nhau nhưng có liên quan với nhau của cùng một dữ liệu cơ bản.

Thứ hai, các đối tượng có thể thay đổi được biết là làm cho việc xử lý các luồng trở thành một nhiệm vụ đầy thách thức. Các luồng làm thay đổi giá trị của một đối tượng mà không đồng bộ hóa phù hợp có thể làm hỏng dữ liệu chứa trong đối tượng đó. Để khắc phục sự cố này, bạn cần sử dụng đồng bộ hóa, điều này có thể gây ra bế tắc. Quan trọng nhất, đồng bộ hóa quá mức làm suy yếu đồng thời.

Cuối cùng, các đối tượng bất biến tạo điều kiện thuận lợi cho việc lập luận về mã của bạn. Để hiểu một đoạn mã liên tục thay đổi một đối tượng, bạn phải nhớ tất cả những thời điểm có thể xảy ra khi dữ liệu cơ bản bị thay đổi. Điều này không đúng với các đối tượng bất biến vì bạn không thể thay đổi dữ liệu hoặc giá trị của chúng.

Với tất cả kiến ​​thức lý thuyết về các đối tượng có thể thay đổi và không thể thay đổi này, bạn đã sẵn sàng đi sâu vào các kiểu dữ liệu có thể thay đổi được tích hợp sẵn của Python.

Các kiểu dữ liệu tích hợp bất biến trong Python

Như bạn đã biết, Python cung cấp một tập hợp phong phú các kiểu dữ liệu dựng sẵn không thể thay đổi. Các loại số, chẳng hạn như intfloatvà complex, có thể chứa các đối tượng một mục mà bạn không thể thay đổi trong quá trình thực thi mã của mình. Những loại này là bất biến. Trong Python, boollớp hỗ trợ kiểu Boolean là lớp con của int. Vì vậy, loại này cũng là bất biến.

Khi nói đến các loại bộ sưu tập, strbytesvà tuplecũng không thay đổi mặc dù chúng có thể lưu trữ các giá trị nhiều mục.

Như bạn có thể kết luận, phần lớn các kiểu dữ liệu dựng sẵn trong Python là bất biến. Trong các phần tiếp theo, bạn sẽ tìm hiểu sâu hơn một chút về cách thức hoạt động của từng loại bất biến này và tính bất biến của chúng có thể ảnh hưởng đến mã của bạn như thế nào.

Số

Các số là ví dụ đầu tiên và phổ biến nhất về các kiểu dựng sẵn bất biến trong Python. Bạn sẽ không có cách nào để truy cập vào phần bên trong của một giá trị số. Do hạn chế này, bạn sẽ không thể thay đổi giá trị của nó mà không thay đổi danh tính của nó. Điều này đúng với tất cả các kiểu số dựng sẵn— intfloatvà complex—như bạn đã học.

Trong Python, khi bạn muốn sử dụng một đối tượng nhất định trong toàn bộ mã của mình, bạn thường gán đối tượng đó cho một biến và sau đó sử dụng lại biến đó bất cứ khi nào bạn cần. Bây giờ hãy xem xét ví dụ sau về một biến trỏ đến một giá trị số:

>>>
>>> number = 314
>>> number
314

>>> id(number)
9402151432

Trong ví dụ này, bạn sử dụng một câu lệnh gán để tạo một biến mới chứa tham chiếu đến một số nguyên. Hàm id()trả về danh tính của số.

Bây giờ giả sử rằng bạn không biết các biến Python hoạt động như thế nào và bạn nghĩ rằng tôi có thể thay đổi giá trị của biến số nguyên này bằng một phép gán khác :

>>>
>>> number = 7
>>> number
7

>>> id(number)
4343439784

Nếu bạn so sánh giá trị trả về của id()trong ví dụ này với giá trị bạn nhận được trong ví dụ trước, thì bạn sẽ lưu ý rằng chúng khác nhau. Vì vậy, thay vì cập nhật giá trị của number, bạn đã tạo một giá trị hoàn toàn mới và khiến biến của bạn tham chiếu đến nó.

Khi bạn đã thay đổi numberthành tham chiếu đến 7, thì cái cũ 314sẽ được thu gom rác, giúp giải phóng bộ nhớ được chỉ định để lưu trữ đối tượng.

Khi nói đến số, Python chỉ cho phép bạn gán lại tên biến để trỏ đến một giá trị số mới tồn tại ở một địa chỉ bộ nhớ hoàn toàn khác. Nó không cho phép bạn thay đổi giá trị được lưu trữ tại địa chỉ bộ nhớ ban đầu. Đó là lý do tại sao 314có danh tính 9402151432, và 7có danh tính 4343439784. Hành vi này là cơ sở của tính bất biến trong các loại số.

Bởi vì các kiểu số là bất biến, không quan trọng bạn có bao nhiêu biến trỏ đến một đối tượng nhất định. Mọi tham chiếu sẽ trỏ đến cùng một giá trị cho đến khi bạn gán lại tên biến một cách rõ ràng:

>>>
>>> word_counter = letter_counter = 0
>>> id(word_counter)
4343439560
>>> id(letter_counter)
4343439560

>>> word_counter += 1
>>> word_counter
1
>>> id(word_counter)
4343439592

>>> letter_counter
0
>>> id(letter_counter)
4343439560

Trong ví dụ này, bạn sử dụng phép gán nhiều lần để tạo hai biến tham chiếu đến cùng một số. Sau đó, cả hai biến giữ cùng một tham chiếu và do đó trỏ đến cùng một phiên bản của số 0.

Nếu bạn chỉ định lại một trong hai biến để giữ một số mới, thì biến thứ hai sẽ vẫn trỏ đến số ban đầu. Đó là lý do tại sao sau khi thực hiện, word_counter += 1,hàm id()trả về một số nhận dạng khác. Lưu ý cách letter_countergiữ dữ liệu gốc.

Booleans

Python có một kiểu dựng sẵn boolcó thể nhận hai giá trị có thể có: Truehoặc False. Các giá trị này là các hằng số tích hợp lần lượt được đặt thành 1và 0. Loại boollà một lớp con của int. Để xác nhận các tính năng nội bộ này của bool, hãy tiếp tục và chạy mã bên dưới:

>>>
>>> issubclass(bool, int)
True

>>> isinstance(True, int)
True
>>> isinstance(False, int)
True

>>> int(True)
1
>>> int(False)
0

Tại đây, trước tiên bạn gọi hàm có sẵn issubclass()để kiểm tra xem đó boolcó thực sự là một lớp con của int. Sau đó, bạn gọi isinstance()để kiểm tra xem cả hai Truevà Falsecó phải là phiên bản của int. Cuối cùng, bạn gọi int()để khám phá Truecó giá trị là 1và Falsecó giá trị là 0.

Bởi vì boolloại là một lớp con của int, nên nó kế thừa tính bất biến của lớp cha:

>>>
>>> has_permission = True
>>> id(has_permission)
4342432520

>>> has_permission = False
>>> id(has_permission)
4342432552

Trong ví dụ này, bạn đã không thay đổi giá trị của has_permissiontừ Truethành False. Bạn thực sự đã chỉ định lại has_permission, hiện đề cập đến một đối tượng khác với danh tính khác.

Mã này hoạt động như thế này vì các phép gán liên tiếp cho một biến làm cho biến đó tham chiếu đến các đối tượng hoàn toàn khác nhau mỗi lần thay vì thay đổi đối tượng tại chỗ. Lưu ý rằng hành vi này không phụ thuộc vào khả năng thay đổi của đối tượng mà phụ thuộc vào cách thức hoạt động của các phép gán trong Python.

byte

Kiểu dựng sẵn bytescũng là một kiểu bất biến trong Python. Như tên gọi của nó, byteslưu trữ dữ liệu nhị phân. Ký tự byte có thể trông khá giống với ký tự chuỗi vì cú pháp của chúng hầu hết giống với cú pháp của ký tự chuỗi. Bạn chỉ cần thêm một btiền tố:

>>>
>>> greeting_str = "Hello, World!"
>>> type(greeting_str)
<class 'str'>

>>> greeting_bytes = b"Hello, World!"
>>> type(greeting_bytes)
<class 'bytes'>

Trong ví dụ đầu tiên, bạn tạo một đối tượng chuỗi bình thường bằng cách sử dụng một số văn bản dưới dạng chữ. Trong ví dụ thứ hai, bạn sử dụng cùng một văn bản để tạo một bytesđối tượng. Để làm điều này, bạn thêm btiền tố vào văn bản của mình. Phần còn lại của cú pháp hoàn toàn tương thích giữa các chuỗi và byte, bao gồm cả việc sử dụng các kết hợp trích dẫn khác nhau.

Một sự khác biệt đáng kể giữa chuỗi và byte là byte sau chỉ cho phép các ký tự ASCII theo nghĩa đen của nó. Nếu bạn cần lưu trữ một giá trị nhị phân trên 127 trong một bytesđối tượng, thì bạn phải nhập giá trị đó bằng trình tự thoát thích hợp. Ngoài ra, bạn có thể biến một chuỗi Python thành một bytesđối tượng bằng cách sử dụng mã hóa ký tự cụ thể và .encode()phương thức:

>>>
>>> bytes("Español".encode("utf-8"))
b'Espa\xc3\xb1ol'

Trong ví dụ này, ký tự "ñ"có điểm Unicode lớn hơn 127. Tuy nhiên, bạn có thể lưu trữ giá trị trong đối tượng byte bằng cách sử dụng phương thức mã hóa với mã hóa ký tự thích hợp.

Giống như các chuỗi thông thường, byte cũng không thay đổi. Nếu bạn cố gắng thay đổi một ký tự trong một bytesđối tượng, thì bạn sẽ gặp lỗi:

>>>
>>> greeting_bytes = b"Hello, World!"
>>> greeting_bytes[0] = "h"
Traceback (most recent call last):
    ...
TypeError: 'bytes' object does not support item assignment

Bạn không thể thay đổi một bytesđối tượng hiện có tại chỗ. Nếu bạn cố gắng làm điều đó, thì bạn sẽ nhận được TypeError, như trong ví dụ trên. Lưu ý rằng thông báo lỗi hầu như giống với thông báo bạn nhận được khi cố gắng thực hiện thao tác tương tự trên một chuỗi.

bộ dữ liệu

Các bộ dữ liệu của Python là một ví dụ khác về tập hợp dữ liệu bất biến. Bạn không thể sửa đổi chúng sau khi được tạo. Giống như chuỗi, bộ dữ liệu là trình tự. Tuy nhiên, không giống như chuỗi, bộ dữ liệu cho phép bạn lưu trữ bất kỳ loại đối tượng nào thay vì chỉ các ký tự. Tính năng này thoạt nhìn có vẻ tuyệt vời. Tuy nhiên, nó có thể gây ra sự cố khi các đối tượng được lưu trữ có thể thay đổi, bạn sẽ tìm hiểu sau trong hướng dẫn này.