Mọi dữ liệu trong Python đều phải thuộc vào một kiểu dữ liệu (data type) nào đó và/hoặc có một cấu trúc dữ liệu (data structure) nào đó. Để ôn lại về data types trong Python, mời bạn xem bài viết sau:
1. Mutable và Immutable là gì?
Trong Python, mọi kiểu dữ liệu đều quy về một trong hai loại sau: mutable hoặc immutable
- Mutable:
- Nhóm này gồm có: List, Set, Dict và các kiểu mutable khác do người dùng định nghĩa
- Giá trị có thể thay đổi tại chỗ được
- Dữ liệu thuộc kiểu mutable thường gây ra Presto-Chango (xem bài Python: Presto-Chango là gì? Hiểu đúng về Name và Value trong Python)
- Immutable:
- Nhóm này gồm có: Numbers, String, Tuple, Frozenset và các kiểu immutable khác do người dùng định nghĩa
- Giá trị không thể thay đổi tại chỗ được
Thế nào là** có thể thay đổi tại chỗ được? **Là khi một biến có thể thay đổi giá trị của nó nhưng ID (có thể hiểu là địa chỉ ô nhớ trên RAM) của biến vẫn giữ nguyên. Tức là bản thân biến đó có những method tác động lên chính nó, làm thay đổi giá trị của nó nhưng địa chỉ trên RAM vẫn không thay đổi. Ở đây, thay đổi giá trị là bất cứ thay đổi nào có thể có. Ví dụ, một list có thể thay đổi giá trị bằng cách thêm vào/bỏ đi một hoặc nhiều phần tử. Hoặc một list có thể thay đổi phần từ hiện tại bằng một list khác,... tất cả đều không làm thay đổi ID của list ban đầu.
2. Một số ví dụ về mutable
Hãy xem ví dụ sau đây
# Khởi tạo một list có ba phần tử >>> L = [1, 2, 3] # Kiểm tra ID của list >>> id(L) 139693861384848 # Thay số 3 bằng số 99 >>> L[2] = 99; print(L) [1, 2, 99] # Kiểm tra lại ID của L >>> id(L) 139693861384848 # Thêm vào L một chuỗi >>> L.append('abc') [1, 2, 99, 'abc'] # Kiểm tra lại ID của L >>> id(L) 139693861384848
Ta thấy ID của biến L không thay đổi mặc dù giá trị của L thay đổi qua lệnh gán và sử dụng phương thức
.append()
. Tuy nhiên, thêm phần tử bằng cách như sau đây thì ID của L sẽ thay đổi (tức là ta sẽ có một biến hoàn toàn mới)>>> print(L) [1, 2, 99, 'abc'] >>> id(L) 139693861384848 # Thêm phần tử vào L >>> L = L + ['edf'] [1, 2, 99, 'abc', 'edf'] # Kiểm tra lại ID >>> id(L) 139693861384632
Ta thấy ID của L đã thay đổi sau khi thực hiện lệnh cộng thêm chuỗi
'edf'
. Nguyên nhân là khi thực hiện lệnh này, Python sẽ tính giá trị bên phải dấu bằng trước, đây là một giá trị hoàn toàn mới (nằm ở một ô nhớ mới), sau đó mới gán giá trị này cho L. Cho nên địa chỉ của L bị thay đổi sang địa chỉ của ô nhớ đang lưu giá trị kia.3. Một số ví dụ immutable
Chúng ta sẽ lấy ví dụ cho biến kiểu Numbes
>>> N = 123 >>> id(N) 94049283973504 # Thay đổi giá trị của N >>> N = 123.0 # ID của N bị thay đổi >>> id(N) 94049297328872
Đối với biến kiểu String và Tuple, mặc dù ta có thể truy cập một phần tử bất kỳ bằng index của nó giống như biến kiểu List, nhưng vì chúng là immutable nên ta không thể thực hiện gán giá trị mới cho phần tử đó được.
# Khởi tạo một tuple đơn giản >>> T = (1, 2, 3) >>> T[0] 1 # Python không cho thay đổi phần tử của tuple >>> T[0] = 9 Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'tuple' object does not support item assignment
Không những không cho thay đổi giá trị bằng lệnh gán trực tiếp phần tử, Python cũng không hỗ trợ phương thức nào để thêm phần tử cho tuple giống như
.append()
của **list. **Lưu ý là chúng ta chỉ đang nói đến "thay đổi giá trị mà không làm thay đổi ID". Bởi vì nếu không quan tâm đến ID thì có rất nhiều cách khác nhau đổi thay đổi tuple. Một trong những cách thường dùng là như trong ví dụ sau đây:>>> T = (1, 2, 3, 4, 5, 6, 7, 8) # Giả sử ta muốn thay đổi số 5 thành số 555. Ta thường làm như sau: >>> L = list(T) >>> L[4] = 555 >>> T = tuple(L) >>> print(T) (1, 2, 3, 4, 555, 6, 7, 8)
Cách phía trên rất hữu ích khi muốn truy cập và thay đổi giá trị qua index. Nếu muốn thêm phần tử vào tuple, ta chỉ việc thực hiện phép cộng
>>> U = (1, 2, 3) # Giả sử ta muốn thêm số 4 vào U >>> U = U + (4,)
4. Kết luận
Như vậy ta đã biết sự khác nhau của kiểu dữ liệu mutable và **immutable. **Ta chỉ cần nhớ: List, Set, Dict là các kiểu mutable, còn lại sẽ là immutable. Ngoài ra, các kiểu dữ liệu do người dùng định nghĩa sẽ phụ thuộc vào thiết kế để là mutable hay immutable. Tip: Để thực sự copy một biến kiểu list
A
vào B
, người ta thường dùng lệnh B = A + []
. Khi đó B
và A
sẽ là hai biến hoàn toàn độc lập. TEXmath