Tuple trong Python là bất biến (immutable): không thể thay đổi, thêm, xóa phần tử sau khi tạo. Tuy nhiên, nếu tuple chứa các đối tượng mutable (như list, dict, set), ta CÓ THỂ sửa đổi nội dung của các đối tượng đó.
Ví dụ
# Tuple chứa list tại index 2
my_tuple = (45, 67, [35, 66, 74], 89, 100)
print(f"Tuple gốc: {my_tuple}")
print(f"ID của list bên trong: {id(my_tuple[2])}")
# Sửa đổi list bên trong tuple (index 2 -> phần tử index 1 của list đó)
my_tuple[2][1] = 63
print(f"\nTuple sau thay đổi: {my_tuple}")
print(f"ID của list bên trong: {id(my_tuple[2])} (giữ nguyên)")
# Thử thay đổi trực tiếp phần tử tuple -> LỖI
try:
my_tuple[0] = 999
except TypeError as e:
print(f"\nLỗi khi gán my_tuple[0] = 999: {e}")
Kết quả
Tuple gốc: (45, 67, [35, 66, 74], 89, 100) ID của list bên trong: 140123456789 Tuple sau thay đổi: (45, 67, [35, 63, 74], 89, 100) ID của list bên trong: 140123456789 (giữ nguyên) Lỗi khi gán my_tuple[0] = 999: 'tuple' object does not support item assignment
Giải thích
- Tuple
my_tuplechứa 5 phần tử, phần tử index 2 là một list[35, 66, 74]. - Tuple bất biến -> không thể gán
my_tuple[2] = new_list. - NHƯNG list là mutable -> có thể sửa đổi NỘI DUNG:
my_tuple[2][1] = 63. - ID của list không đổi -> cùng đối tượng list, chỉ nội dung thay đổi.
Các kiểu mutable có thể chứa trong tuple
# List
t1 = (1, [2, 3])
t1[1].append(4)
print(t1) # (1, [2, 3, 4])
# Dict
t2 = (1, {'a': 2})
t2[1]['b'] = 3
print(t2) # (1, {'a': 2, 'b': 3})
# Set
t3 = (1, {2, 3})
t3[1].add(4)
print(t3) # (1, {2, 3, 4})
# Custom object
class Box:
def __init__(self, val):
self.val = val
t4 = (Box(10),)
t4[0].val = 20
print(t4[0].val) # 20
Kiểu immutable trong tuple (KHÔNG sửa được)
# String t = (1, "hello") # t[1][0] = 'H' # TypeError: 'str' object does not support item assignment # Tuple lồng tuple t = (1, (2, 3)) # t[1][0] = 99 # TypeError: 'tuple' object does not support item assignment # Number t = (1, 2) # t[1] = 3 # TypeError: 'tuple' object does not support item assignment
Ứng dụng thực tế: Cấu trúc dữ liệu nửa bất biến
# Record: (id, name, tags_list)
# id, name không đổi, tags có thể thêm/bớt
records = [
(1, 'Python', ['backend', 'scripting']),
(2, 'JavaScript', ['frontend', 'backend']),
]
# Thêm tag cho Python
records[0][2].append('data-science')
print(records[0]) # (1, 'Python', ['backend', 'scripting', 'data-science'])
Cảnh báo: Side effect
shared_list = [1, 2] t1 = (shared_list,) t2 = (shared_list,) t1[0].append(3) print(t2) # ([1, 2, 3],) - t2 cũng thay đổi vì cùng tham chiếu list!