M08 — List và Tuple

← 07 - Vòng lặp (for-while) | Tiếp theo → 09 - Dict và Set

Mục tiêu module

  • Tạo, truy cập, sửa đổi list (danh sách)
  • Hiểu mutable (khả biến) vs immutable (bất biến) và bẫy tham chiếu
  • Nắm list comprehension
  • Biết khi nào dùng tuple

Thời lượng: ~8 giờ | Tuần: 12–13

Tuần 12: Mục 1–6 | Tuần 13: Mục 7–12


PHẦN 1 — TUẦN 12

1. List là gì?

List (danh sách) là một dãy có thứ tự, có thể thay đổi, chứa nhiều giá trị.

danh_sach_kh = ["Nguyen Van A", "Tran Thi B", "Le Van C"]
so_luong = [10, 25, 3, 47]
hon_hop = ["KH001", 25, 15000.5, True, None]     # Chứa nhiều kiểu khác nhau
rong = []                                        # List rỗng

1.1. Đặc điểm

Đặc điểmÝ nghĩa
Ordered (có thứ tự)Phần tử giữ đúng thứ tự bạn thêm vào
Mutable (khả biến)Sửa được sau khi tạo
Cho phép trùng lặp[1, 1, 2] hợp lệ
Hỗn hợp kiểuChứa được nhiều kiểu dữ liệu cùng lúc
Đánh chỉ số từ 0Giống chuỗi

1.2. Liên hệ với SQL

Một list chứa các dict chính là tương đương gần nhất của một result set (tập kết quả) trong SQL:

# Tương đương SELECT * FROM KhachHang
khach_hang = [
    {"ma": "KH001", "ten": "Nguyen Van A", "no": 5_000_000},
    {"ma": "KH002", "ten": "Tran Thi B", "no": 12_000_000},
    {"ma": "KH003", "ten": "Le Van C", "no": 0},
]

Cấu trúc này bạn sẽ dùng liên tục ở 16 - Python kết nối Database.


2. Truy cập phần tử

2.1. Indexing

ds = ["A", "B", "C", "D", "E"]
 
print(ds[0])       # A   — phần tử đầu
print(ds[2])       # C
print(ds[-1])      # E   — phần tử cuối
print(ds[-2])      # D
print(len(ds))     # 5
print(ds[5])       # ❌ IndexError: list index out of range

2.2. Slicing — giống hệt chuỗi

ds = ["A", "B", "C", "D", "E"]
 
print(ds[1:4])     # ['B', 'C', 'D']
print(ds[:3])      # ['A', 'B', 'C']
print(ds[3:])      # ['D', 'E']
print(ds[-2:])     # ['D', 'E']
print(ds[::2])     # ['A', 'C', 'E']
print(ds[::-1])    # ['E', 'D', 'C', 'B', 'A']  — đảo ngược

Kỹ năng slicing dùng lại được

Bạn đã học slicing với chuỗi ở 05 - Chuỗi ký tự (String). Cú pháp hoàn toàn giống nhau với list, tuple, và mọi dãy dữ liệu khác. Đây là ví dụ điển hình cho triết lý “một cách hiển nhiên để làm việc đó” của Python.

2.3. List lồng nhau (nested list)

ma_tran = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9],
]
 
print(ma_tran[0])         # [1, 2, 3]
print(ma_tran[0][1])      # 2
print(ma_tran[2][2])      # 9
 
# Duyệt ma trận
for hang in ma_tran:
    for o in hang:
        print(f"{o:>4}", end="")
    print()

3. Mutable — Sửa đổi list

3.1. Sửa phần tử

ds = ["A", "B", "C"]
ds[1] = "X"
print(ds)          # ['A', 'X', 'C']

Nhớ lại: chuỗi không làm được điều này (s[1] = "X" gây TypeError). Đó là khác biệt cốt lõi giữa mutable và immutable.

3.2. Sửa cả một đoạn

ds = ["A", "B", "C", "D", "E"]
ds[1:3] = ["X", "Y", "Z"]
print(ds)          # ['A', 'X', 'Y', 'Z', 'D', 'E']

4. Thêm phần tử

MethodTác dụngVí dụ
append(x)Thêm 1 phần tử vào cuốids.append("D")
insert(i, x)Chèn vào vị trí ids.insert(0, "Z")
extend(iterable)Nối nhiều phần tử vào cuốids.extend(["D","E"])
ds = ["A", "B"]
 
ds.append("C")
print(ds)                    # ['A', 'B', 'C']
 
ds.insert(0, "Z")
print(ds)                    # ['Z', 'A', 'B', 'C']
 
ds.extend(["D", "E"])
print(ds)                    # ['Z', 'A', 'B', 'C', 'D', 'E']

⚠️ append vs extend

a = [1, 2, 3]
a.append([4, 5])
print(a)          # [1, 2, 3, [4, 5]]   <- thêm CẢ LIST làm 1 phần tử
 
b = [1, 2, 3]
b.extend([4, 5])
print(b)          # [1, 2, 3, 4, 5]     <- thêm TỪNG phần tử

Nối list bằng +

a = [1, 2]
b = [3, 4]
c = a + b
print(c)          # [1, 2, 3, 4]
print(a)          # [1, 2]  — a KHÔNG đổi, `+` tạo list mới
a.extend(b)a + b
Sửa aCóKhông
Trả vềNoneList mới

5. Xóa phần tử

CáchTác dụngTrả về
remove(x)Xóa phần tử có giá trị x đầu tiênNone
pop(i)Xóa phần tử ở vị trí i (mặc định cuối)Phần tử bị xóa
del ds[i]Xóa theo vị trí hoặc đoạn—
clear()Xóa sạchNone
ds = ["A", "B", "C", "B", "D"]
 
ds.remove("B")
print(ds)              # ['A', 'C', 'B', 'D']  — chỉ xóa "B" ĐẦU TIÊN
 
x = ds.pop()
print(x, ds)           # D ['A', 'C', 'B']     — pop trả về phần tử bị xóa
 
y = ds.pop(0)
print(y, ds)           # A ['C', 'B']
 
del ds[0]
print(ds)              # ['B']
 
ds.clear()
print(ds)              # []
ds = ["A", "B", "C"]
ds.remove("Z")         # ❌ ValueError: list.remove(x): x not in list

Cách an toàn:

if "Z" in ds:
    ds.remove("Z")

⚠️ Đừng xóa phần tử khi đang duyệt

# ❌ SAI — kết quả không như mong đợi
ds = [1, 2, 3, 4, 5, 6]
for x in ds:
    if x % 2 == 0:
        ds.remove(x)
print(ds)          # [1, 3, 5] ... nhưng đôi khi ra kết quả sai!

Khi xóa phần tử, các chỉ số phía sau bị dịch chuyển, khiến vòng lặp bỏ sót.

# ✅ ĐÚNG — tạo list mới
ds = [1, 2, 3, 4, 5, 6]
ds = [x for x in ds if x % 2 != 0]
print(ds)          # [1, 3, 5]
 
# ✅ Hoặc duyệt trên bản sao
ds = [1, 2, 3, 4, 5, 6]
for x in ds[:]:        # ds[:] tạo bản sao
    if x % 2 == 0:
        ds.remove(x)

6. Các method khác

ds = [30, 10, 50, 20, 10, 40]
 
print(len(ds))            # 6
print(ds.count(10))       # 2   — đếm số lần xuất hiện
print(ds.index(50))       # 2   — vị trí đầu tiên
print(min(ds))            # 10
print(max(ds))            # 50
print(sum(ds))            # 160
print(sum(ds) / len(ds))  # 26.666666666666668
 
# Sắp xếp TẠI CHỖ (sửa list gốc)
ds.sort()
print(ds)                 # [10, 10, 20, 30, 40, 50]
 
ds.sort(reverse=True)
print(ds)                 # [50, 40, 30, 20, 10, 10]
 
# Đảo ngược tại chỗ
ds.reverse()
print(ds)                 # [10, 10, 20, 30, 40, 50]

⚠️ sort() vs sorted()

ds = [3, 1, 2]
 
ds.sort()                 # Sửa ds, trả về None
print(ds)                 # [1, 2, 3]
 
ds2 = [3, 1, 2]
moi = sorted(ds2)         # KHÔNG sửa ds2, trả về list mới
print(ds2, moi)           # [3, 1, 2] [1, 2, 3]
ds.sort()sorted(ds)
Sửa list gốcCóKhông
Trả vềNoneList mới
Dùng được vớiChỉ listMọi dãy (chuỗi, tuple, dict…)

Lỗi kinh điển

ds = [3, 1, 2].sort()
print(ds)          # None !!!

sort() trả về None, không trả về list. Phải viết:

ds = [3, 1, 2]
ds.sort()          # ✅
# hoặc
ds = sorted([3, 1, 2])   # ✅

Sắp xếp phức tạp với key

ds = ["banana", "Apple", "cherry"]
 
print(sorted(ds))                    # ['Apple', 'banana', 'cherry'] — hoa trước
print(sorted(ds, key=str.lower))     # ['Apple', 'banana', 'cherry'] — không phân biệt hoa thường
print(sorted(ds, key=len))           # ['Apple', 'banana', 'cherry'] — theo độ dài
khach_hang = [
    {"ten": "Nguyen Van A", "no": 5_000_000},
    {"ten": "Tran Thi B", "no": 12_000_000},
    {"ten": "Le Van C", "no": 800_000},
]
 
# Sắp xếp theo công nợ giảm dần — tương đương ORDER BY No DESC
theo_no = sorted(khach_hang, key=lambda kh: kh["no"], reverse=True)
 
for kh in theo_no:
    print(f"{kh['ten']:<20}{kh['no']:>15,}")

lambda là gì?

lambda kh: kh["no"] là một hàm ẩn danh (anonymous function) — hàm nhỏ viết trên một dòng. Nó nói: “với mỗi phần tử kh, hãy lấy giá trị kh["no"] để làm khóa sắp xếp”. Bạn sẽ học kỹ ở 10 - Hàm (Function). Giờ chỉ cần nhận biết mẫu này.


PHẦN 2 — TUẦN 13

7. ⚠️ Bẫy tham chiếu (Reference Trap)

Đây là chủ đề quan trọng nhất của module này. Rất nhiều lỗi khó hiểu bắt nguồn từ đây.

7.1. Gán list KHÔNG tạo bản sao

a = [1, 2, 3]
b = a              # b KHÔNG phải bản sao, b là NHÃN THỨ HAI dán lên cùng đối tượng
 
b.append(4)
print(b)           # [1, 2, 3, 4]
print(a)           # [1, 2, 3, 4]   <- a CŨNG ĐỔI!

Nhớ lại khái niệm “biến là nhãn dán” ở 03 - Biến và kiểu dữ liệu. Với số và chuỗi (immutable), điều này không gây hậu quả. Với list (mutable), nó gây ra lỗi rất khó tìm.

Kiểm chứng:

a = [1, 2, 3]
b = a
print(a is b)      # True — cùng một đối tượng
print(id(a) == id(b))   # True

7.2. Cách tạo bản sao thật (shallow copy)

a = [1, 2, 3]
 
b1 = a.copy()          # Cách 1 — rõ ràng nhất
b2 = a[:]              # Cách 2 — slicing
b3 = list(a)           # Cách 3 — ép kiểu
 
b1.append(4)
print(a)               # [1, 2, 3]  — a không đổi ✅

7.3. Shallow copy chưa đủ với list lồng nhau

a = [[1, 2], [3, 4]]
b = a.copy()
 
b[0].append(99)
print(a)               # [[1, 2, 99], [3, 4]]  <- a VẪN ĐỔI!

Shallow copy (sao chép nông) chỉ sao chép lớp ngoài. Các list bên trong vẫn được chia sẻ.

Giải pháp: deep copy (sao chép sâu)

import copy
 
a = [[1, 2], [3, 4]]
b = copy.deepcopy(a)
 
b[0].append(99)
print(a)               # [[1, 2], [3, 4]]  ✅
print(b)               # [[1, 2, 99], [3, 4]]

Quy tắc thực dụng

  • List phẳng (chỉ chứa số, chuỗi) → .copy() là đủ
  • List lồng nhau (chứa list, dict) → dùng copy.deepcopy()

8. List Comprehension

List comprehension là cú pháp tạo list ngắn gọn — đặc trưng nổi tiếng nhất của Python.

8.1. Cú pháp cơ bản

[<biểu thức> for <biến> in <dãy>]
# ❌ Cách dài
binh_phuong = []
for i in range(1, 6):
    binh_phuong.append(i ** 2)
print(binh_phuong)     # [1, 4, 9, 16, 25]
 
# ✅ List comprehension
binh_phuong = [i ** 2 for i in range(1, 6)]
print(binh_phuong)     # [1, 4, 9, 16, 25]

8.2. Có điều kiện lọc

[<biểu thức> for <biến> in <dãy> if <điều kiện>]
so_chan = [i for i in range(1, 21) if i % 2 == 0]
print(so_chan)         # [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]

Tương đương SQL:

SELECT So FROM Bang WHERE So % 2 = 0

8.3. Có if/else trong biểu thức

# Chú ý: if/else đứng TRƯỚC for
ket_qua = ["Chan" if i % 2 == 0 else "Le" for i in range(1, 6)]
print(ket_qua)         # ['Le', 'Chan', 'Le', 'Chan', 'Le']
Vị tríVai trò
[x for x in ds if <đk>]Lọc — chỉ giữ phần tử thỏa mãn
[a if <đk> else b for x in ds]Biến đổi — mọi phần tử đều giữ, chỉ đổi giá trị

8.4. Ví dụ thực tế

# Ép kiểu hàng loạt
chuoi_so = ["10", "20", "30"]
so = [int(x) for x in chuoi_so]
print(so)                                # [10, 20, 30]
 
# Chuẩn hóa dữ liệu
ten_tho = ["  nguyen van a  ", "TRAN THI B", "le van c"]
ten_chuan = [t.strip().title() for t in ten_tho]
print(ten_chuan)                         # ['Nguyen Van A', 'Tran Thi B', 'Le Van C']
 
# Lọc + biến đổi
gia = [100000, 250000, 80000, 500000]
gia_giam = [g * 0.9 for g in gia if g >= 100000]
print(gia_giam)                          # [90000.0, 225000.0, 450000.0]
 
# Trích một cột từ list các dict — tương đương SELECT Ten FROM ...
kh = [
    {"ma": "KH001", "ten": "A", "no": 5_000_000},
    {"ma": "KH002", "ten": "B", "no": 0},
]
ten_kh = [x["ten"] for x in kh]
print(ten_kh)                            # ['A', 'B']
 
# Lọc + trích — SELECT Ma FROM KH WHERE No > 0
co_no = [x["ma"] for x in kh if x["no"] > 0]
print(co_no)                             # ['KH001']

8.5. Lồng nhau

ma_tran = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
 
# Làm phẳng ma trận
phang = [o for hang in ma_tran for o in hang]
print(phang)           # [1, 2, 3, 4, 5, 6, 7, 8, 9]

Thứ tự đọc: giống hệt vòng lặp lồng nhau viết theo hàng ngang.

Đừng lạm dụng

List comprehension chỉ nên dùng khi nó dễ đọc hơn vòng lặp thường. Nếu phải lồng 3 cấp hoặc điều kiện phức tạp, hãy dùng vòng lặp for bình thường.

# ❌ Quá khó đọc
kq = [x*y for x in range(10) if x%2==0 for y in range(10) if y%3==0 if x+y>5]

9. Tuple

Tuple là dãy có thứ tự nhưng immutable (không sửa được).

9.1. Tạo tuple

t = (1, 2, 3)
t2 = 1, 2, 3              # Dấu ngoặc có thể bỏ
t3 = ()                   # Tuple rỗng
t4 = (5,)                 # ⚠️ Tuple 1 phần tử — BẮT BUỘC có dấu phẩy
t5 = (5)                  # ❌ Đây là số 5, không phải tuple!
 
print(type(t4))           # <class 'tuple'>
print(type(t5))           # <class 'int'>

9.2. Truy cập — giống list

t = ("A", "B", "C")
print(t[0])        # A
print(t[-1])       # C
print(t[0:2])      # ('A', 'B')
print(len(t))      # 3
print("B" in t)    # True

9.3. Không sửa được

t = (1, 2, 3)
t[0] = 99          # ❌ TypeError: 'tuple' object does not support item assignment
t.append(4)        # ❌ AttributeError: 'tuple' object has no attribute 'append'

9.4. Khi nào dùng tuple thay list?

Trường hợpLý do
Dữ liệu không được phép thay đổiBảo vệ khỏi sửa nhầm (hằng số, cấu hình)
Trả về nhiều giá trị từ hàmQuy ước chuẩn của Python
Làm khóa của dictionaryList không làm được vì mutable
Tối ưu bộ nhớTuple nhẹ hơn và nhanh hơn list
# Hằng số
MAU_SAC_HOP_LE = ("do", "xanh", "vang")
NGAY_TRONG_TUAN = ("T2", "T3", "T4", "T5", "T6", "T7", "CN")
 
# Tọa độ, cặp giá trị cố định
diem = (10.5, 20.3)

9.5. Unpacking — Giải nén tuple

t = ("KH001", "Nguyen Van A", 5_000_000)
 
ma, ten, no = t
print(ma)          # KH001
print(ten)         # Nguyen Van A
print(no)          # 5000000

Số biến bên trái phải khớp số phần tử:

a, b = (1, 2, 3)      # ❌ ValueError: too many values to unpack

Dùng * để gom phần dư:

a, *con_lai = (1, 2, 3, 4, 5)
print(a, con_lai)          # 1 [2, 3, 4, 5]
 
dau, *giua, cuoi = (1, 2, 3, 4, 5)
print(dau, giua, cuoi)     # 1 [2, 3, 4] 5

Unpacking cũng hoạt động với list:

ds = [10, 20, 30]
x, y, z = ds
print(x, y, z)             # 10 20 30

Và đây chính là cơ chế đằng sau mẹo hoán đổi biến:

a, b = 1, 2
a, b = b, a          # Vế phải tạo tuple (b, a), rồi giải nén vào a, b

10. Chuyển đổi qua lại

t = (1, 2, 3)
ds = list(t)              # tuple -> list
print(ds)                 # [1, 2, 3]
 
ds2 = [4, 5, 6]
t2 = tuple(ds2)           # list -> tuple
print(t2)                 # (4, 5, 6)
 
s = "PYTHON"
print(list(s))            # ['P', 'Y', 'T', 'H', 'O', 'N']
print(tuple(s))           # ('P', 'Y', 'T', 'H', 'O', 'N')

11. Chương trình mẫu tổng hợp

"""Quản lý danh mục hàng hóa — tổng hợp M02 đến M08."""
 
# Dữ liệu: mỗi mặt hàng là một tuple (ma, ten, don_vi, so_luong, don_gia)
hang_hoa = [
    ("VT001", "Ban lam viec",  "Cai",  3,  2_500_000),
    ("VT002", "Ghe xoay",      "Cai", 10,    850_000),
    ("VT003", "Tu ho so",      "Cai",  2,  4_200_000),
    ("VT004", "May in laser",  "Cai",  1,  6_500_000),
    ("VT005", "Giay A4",       "Ram", 50,     65_000),
]
 
DO_RONG = 78
 
def in_duong_ke():
    print("-" * DO_RONG)
 
# ---------- In bảng ----------
print("=" * DO_RONG)
print("BANG KE HANG HOA TON KHO".center(DO_RONG))
print("=" * DO_RONG)
print(f"{'STT':<5}{'MA':<8}{'TEN HANG':<20}{'DVT':<6}{'SL':>6}{'DON GIA':>14}{'THANH TIEN':>17}")
in_duong_ke()
 
tong_gia_tri = 0
for stt, (ma, ten, dvt, sl, gia) in enumerate(hang_hoa, start=1):
    thanh_tien = sl * gia
    tong_gia_tri += thanh_tien
    print(f"{stt:<5}{ma:<8}{ten:<20}{dvt:<6}{sl:>6}{gia:>14,}{thanh_tien:>17,}")
 
in_duong_ke()
print(f"{'TONG GIA TRI TON KHO':<61}{tong_gia_tri:>17,}")
print("=" * DO_RONG)
 
# ---------- Thống kê ----------
gia_tri_tung_mat = [sl * gia for _, _, _, sl, gia in hang_hoa]
 
print()
print("THONG KE:")
print(f"  So mat hang        : {len(hang_hoa)}")
print(f"  Tong gia tri       : {sum(gia_tri_tung_mat):,}")
print(f"  Gia tri lon nhat   : {max(gia_tri_tung_mat):,}")
print(f"  Gia tri nho nhat   : {min(gia_tri_tung_mat):,}")
print(f"  Gia tri trung binh : {sum(gia_tri_tung_mat) / len(gia_tri_tung_mat):,.0f}")
 
# ---------- Lọc: các mặt hàng giá trị >= 5 triệu ----------
print()
print("CAC MAT HANG CO GIA TRI TU 5 TRIEU:")
hang_lon = [(ma, ten, sl * gia) for ma, ten, _, sl, gia in hang_hoa if sl * gia >= 5_000_000]
 
if hang_lon:
    for ma, ten, gt in sorted(hang_lon, key=lambda x: x[2], reverse=True):
        print(f"  {ma} - {ten:<20}: {gt:>15,}")
else:
    print("  (Khong co)")

12. Thực hành bắt buộc

Bài 1 — Cơ bản với list

Cho ds = [15, 8, 42, 4, 23, 16, 15, 8], in ra:

  1. Phần tử đầu, cuối, và 3 phần tử giữa
  2. Danh sách đảo ngược
  3. Danh sách đã sắp xếp tăng dần (không sửa ds gốc)
  4. Tổng, trung bình, min, max
  5. Số lần xuất hiện của 15
  6. Danh sách không trùng lặp (gợi ý: dùng set — xem 09 - Dict và Set)

Bài 2 — Thao tác thêm/xóa

Viết chương trình quản lý danh sách công việc (to-do list) với menu:

1. Them cong viec
2. Xoa cong viec (theo so thu tu)
3. Xem danh sach
4. Danh dau hoan thanh
0. Thoat

Bài 3 — Bẫy tham chiếu

Dự đoán kết quả trước khi chạy, giải thích tại sao:

a = [1, 2, 3]
b = a
c = a.copy()
a.append(4)
print(a, b, c)
 
x = [[1, 2], [3, 4]]
y = x.copy()
y[0][0] = 99
print(x, y)

Bài 4 — List comprehension

Dùng list comprehension (mỗi câu 1 dòng):

  1. Tạo list bình phương các số từ 1 đến 20
  2. Lọc các số chia hết cho 7 trong khoảng 1–200
  3. Chuyển ["10", "abc", "20", "xyz"] thành [10, 20] (bỏ phần tử không phải số)
  4. Từ [" a ", "B", " c "] tạo ["A", "B", "C"]
  5. Từ ma trận 3×3, lấy các phần tử trên đường chéo chính

Bài 5 — Thống kê điểm

Cho danh sách điểm [8.5, 6.0, 9.5, 4.5, 7.0, 5.5, 9.0, 3.0], tính và in:

  • Điểm cao nhất, thấp nhất, trung bình
  • Số học sinh đạt (≥ 5) và không đạt
  • Danh sách điểm đã sắp xếp giảm dần
  • Xếp loại từng điểm (dùng list comprehension với if/else)

Bài 6 — Bảng lương

Cho 3 list song song:

ho_ten = ["Nguyen Van A", "Tran Thi B", "Le Van C", "Pham Thi D"]
chuc_vu = ["Truong phong", "Nhan vien", "Nhan vien", "Pho phong"]
luong = [25_000_000, 12_000_000, 11_500_000, 18_000_000]

Dùng zip() và enumerate() in bảng lương có STT, tính tổng và trung bình. Sắp xếp theo lương giảm dần.

Bài 7 — Tuple và unpacking

  1. Viết hàm (dùng biến thường cũng được) tính đồng thời tổng, hiệu, tích của 2 số, trả về tuple, rồi unpacking ra 3 biến
  2. Cho diem = [(1,2), (3,4), (5,6)], dùng vòng lặp với unpacking để in x=1, y=2 cho từng cặp

Bài 8 — Ma trận

Cho ma trận 3×3, viết chương trình:

  1. In ma trận dạng bảng
  2. Tính tổng mỗi hàng
  3. Tính tổng mỗi cột
  4. Tính tổng đường chéo chính
  5. Tìm phần tử lớn nhất và vị trí của nó

13. Tự kiểm tra

  • Tôi phân biệt được list (mutable) và tuple (immutable)
  • Tôi biết append khác extend
  • Tôi biết sort() sửa list gốc và trả về None, còn sorted() trả về list mới
  • Tôi hiểu bẫy tham chiếu: b = a không tạo bản sao
  • Tôi biết dùng .copy() và copy.deepcopy()
  • Tôi viết được list comprehension có điều kiện lọc
  • Tôi biết unpacking tuple và * gom phần dư
  • Tôi biết dùng key=lambda ... để sắp xếp theo tiêu chí

14. Tài liệu chính thức

NguồnNội dungLink
Tutorial — ListsNhập môn listhttps://docs.python.org/3/tutorial/introduction.html#lists
Data StructuresList method, comprehension, tuplehttps://docs.python.org/3/tutorial/datastructures.html
Sequence TypesĐặc tả list, tuple, rangehttps://docs.python.org/3/library/stdtypes.html#sequence-types-list-tuple-range
copy moduleShallow và deep copyhttps://docs.python.org/3/library/copy.html
Sorting HOW TOHướng dẫn sắp xếp nâng caohttps://docs.python.org/3/howto/sorting.html

Tiếp theo → 09 - Dict và Set