1. Kiểu Số: Số Nguyên (int) và Số Thực (float)
1.1 Định nghĩa
Trong Python, các kiểu dữ liệu số được sử dụng để lưu trữ giá trị số. Có hai loại chính là số nguyên và số thực.
# Định nghĩa số nguyên (int)
so_tuoi = 30 # Thực chất là so_tuoi = int(30)
# Định nghĩa số thực (float)
gia_tien = 59.99 # Thực chất là gia_tien = float(59.99)
# Lưu ý: Cú pháp Tên_Kiểu(...) thường dùng để gọi một hàm tạo hoặc chuyển đổi kiểu.
# Ví dụ: print(...) gọi hàm in
# int(...) gọi hàm tạo số nguyên
# float(...) gọi hàm tạo số thực
1.2 Chuyển đổi kiểu
# Chuyển đổi sang số nguyên (int)
# int() có thể chuyển đổi chuỗi chứa hoàn toàn số nguyên. Nếu có ký tự không phải số, sẽ báo lỗi.
chuoi_so = '456'
ket_qua_int = int(chuoi_so)
print(f"Giá trị: {ket_qua_int}, Kiểu: {type(ket_qua_int)}") # Kết quả: Giá trị: 456, Kiểu: <class 'int'>
# int('7.8') # Lỗi: ValueError vì chuỗi chứa dấu chấm thập phân
# Chuyển đổi cơ số
# Chuyển từ thập phân sang các cơ số khác
print(bin(5)) # Kết quả: '0b101' (nhị phân)
print(oct(10)) # Kết quả: '0o12' (bát phân)
print(hex(16)) # Kết quả: '0x10' (thập lục phân)
# Chuyển từ các cơ số khác về thập phân
print(int('0b101', 2)) # Kết quả: 5
print(int('0o12', 8)) # Kết quả: 10
print(int('0x10', 16)) # Kết quả: 16
# Chuyển đổi sang số thực (float)
# float() có thể chuyển đổi chuỗi chứa số thực hoặc số nguyên.
chuoi_thap_phan = '99.5'
ket_qua_float = float(chuoi_thap_phan)
print(f"Giá trị: {ket_qua_float}, Kiểu: {type(ket_qua_float)}") # Kết quả: Giá trị: 99.5, Kiểu: <class 'float'>
1.3 Sử dụng
Các kiểu số chủ yếu được dùng cho các phép toán số học và so sánh. Ngoài việc kết hợp với các toán tử, chúng không có nhiều phương thức tích hợp cần ghi nhớ.
2. Kiểu Chuỗi (str)
2.1 Định nghĩa
Chuỗi là một dãy ký tự được đặt trong dấu nháy đơn ('), nháy kép (") hoặc ba nháy (''' hoặc """).
# Định nghĩa chuỗi với nháy đơn
ten_san_pham = 'Laptop XYZ' # Thực chất: ten_san_pham = str('Laptop XYZ')
# Định nghĩa chuỗi với nháy kép
mo_ta = "Sản phẩm chất lượng cao" # Thực chất: mo_ta = str("Sản phẩm chất lượng cao")
# Định nghĩa chuỗi với ba nháy (thường dùng cho chuỗi đa dòng)
noi_dung_dai = """Đây là một đoạn
chuỗi văn bản
gồm nhiều dòng.""" # Thực chất: noi_dung_dai = str("""...""")
2.2 Chuyển đổi kiểu
Phương thức str() có thể chuyển đổi hầu hết mọi kiểu dữ liệu thành dạng chuỗi.
# Chuyển đổi từ danh sách sang chuỗi
print(type(str([10, 20, 30]))) # Kết quả: <class 'str'>, chuỗi: '[10, 20, 30]'
# Chuyển đổi từ từ điển sang chuỗi
print(type(str({"ten": "An", "tuoi": 25}))) # Kết quả: <class 'str'>, chuỗi: "{'ten': 'An', 'tuoi': 25}"
# Chuyển đổi từ tuple sang chuỗi
print(type(str((100, 200, 300)))) # Kết quả: <class 'str'>, chuỗi: '(100, 200, 300)'
# Chuyển đổi từ tập hợp sang chuỗi
print(type(str({1, 2, 3, 4}))) # Kết quả: <class 'str'>, chuỗi: '{1, 2, 3, 4}'
2.3 Sử dụng
2.3.1 Các thao tác quan trọng
chuoi_goc = 'Xin chào Python!'
# 1. Truy cập ký tự bằng chỉ mục (index)
# Chỉ mục dương (từ trái sang, bắt đầu từ 0)
print(chuoi_goc[4]) # Kết quả: 'c'
# Chỉ mục âm (từ phải sang, bắt đầu từ -1)
print(chuoi_goc[-7]) # Kết quả: 'P'
# Lưu ý: Chuỗi là bất biến, không thể thay đổi ký tự tại một chỉ mục
# chuoi_goc[0] = 'x' # Sẽ báo lỗi TypeError
# 2. Cắt chuỗi (Slicing) - [start:end:step]
# Lấy từ chỉ mục 0 đến (không bao gồm) 8
print(chuoi_goc[0:8]) # Kết quả: 'Xin chào'
# Với bước nhảy: Lấy ký tự tại chỉ mục 0, 2, 4, 6...
print(chuoi_goc[0:9:2]) # Kết quả: 'Xnco'
# Đảo ngược chuỗi
print(chuoi_goc[::-1]) # Kết quả: '!nohtyP oàhc niX'
# 3. Độ dài chuỗi (len)
print(len(chuoi_goc)) # Kết quả: 15 (cả khoảng trắng và dấu câu)
# 4. Kiểm tra thành viên (in và not in)
print('Chào' in chuoi_goc) # Kết quả: True
print('Java' not in chuoi_goc) # Kết quả: True
# 5. Xóa ký tự ở đầu/cuối (strip)
chuoi_khoang_trang = ' dữ liệu quan trọng \n'
print(chuoi_khoang_trang.strip()) # Kết quả: 'dữ liệu quan trọng' (mặc định xóa khoảng trắng, tab, xuống dòng)
chuoi_ky_tu = '###Python###'
print(chuoi_ky_tu.strip('#')) # Kết quả: 'Python' (xóa ký tự '#')
# 6. Tách chuỗi (split)
chuoi_cau = 'Xin chào thế giới'
print(chuoi_cau.split()) # Kết quả: ['Xin', 'chào', 'thế', 'giới'] (mặc định tách bằng khoảng trắng)
dia_chi_ip = '192.168.1.10'
print(dia_chi_ip.split('.')) # Kết quả: ['192', '168', '1', '10'] (tách bằng '.')
# 7. Duyệt chuỗi (Loop)
chuoi_duyet = 'Lập trình Python'
for ky_tu in chuoi_duyet:
print(ky_tu)
# Kết quả:
# L
# ậ
# p
# ...
# n
2.3.2 Các thao tác nâng cao
chuoi_moi = '---dữ liệu---'
# 1. strip(), lstrip(), rstrip()
print(chuoi_moi.strip('-')) # Kết quả: 'dữ liệu' (xóa cả hai phía)
print(chuoi_moi.lstrip('-')) # Kết quả: 'dữ liệu---' (chỉ xóa bên trái)
print(chuoi_moi.rstrip('-')) # Kết quả: '---dữ liệu' (chỉ xóa bên phải)
chuoi_chuyen_doi = 'PyThOn PrOgRaMmInG'
# 2. lower(), upper()
print(chuoi_chuyen_doi.lower()) # Kết quả: 'python programming' (chuyển tất cả thành chữ thường)
print(chuoi_chuyen_doi.upper()) # Kết quả: 'PYTHON PROGRAMMING' (chuyển tất cả thành chữ hoa)
chuoi_kiem_tra = 'python.org'
# 3. startswith(), endswith()
print(chuoi_kiem_tra.startswith('py')) # Kết quả: True
print(chuoi_kiem_tra.endswith('.org')) # Kết quả: True
print(chuoi_kiem_tra.startswith('java')) # Kết quả: False
# 4. Định dạng chuỗi với format()
# Định dạng bằng tên tham số (không cần theo thứ tự)
cau_chao = 'Chào bạn {ten}, bạn {tuoi} tuổi phải không?'
ket_qua = cau_chao.format(tuoi=30, ten='Minh')
print(ket_qua) # Kết quả: 'Chào bạn Minh, bạn 30 tuổi phải không?'
# Sử dụng một tham số nhiều lần
thong_tin_du_lieu = 'Tên: {username}, ID: {id}, Username lại: {username}'.format(username='admin', id=101)
print(thong_tin_du_lieu) # Kết quả: 'Tên: admin, ID: 101, Username lại: admin'
# Định dạng theo vị trí (giống %s)
cau_don_gian = 'Giá trị thứ nhất: {}, Giá trị thứ hai: {}'.format('text', 123)
print(cau_don_gian) # Kết quả: 'Giá trị thứ nhất: text, Giá trị thứ hai: 123'
# Định dạng theo chỉ mục (có thể đảo ngược vị trí)
cau_chi_muc = 'Sản phẩm {1} có giá {0} USD.'.format(500, 'Máy tính')
print(cau_chi_muc) # Kết quả: 'Sản phẩm Máy tính có giá 500 USD.'
# 5. split(), rsplit()
duong_dan_tep = 'C:/Users/Documents/file.txt'
# Tách từ trái sang, giới hạn 2 lần
print(duong_dan_tep.split('/', 2)) # Kết quả: ['C:', 'Users', 'Documents/file.txt']
chuoi_phan_tach = 'a|b|c|d'
# Tách từ phải sang, giới hạn 1 lần
print(chuoi_phan_tach.rsplit('|', 1)) # Kết quả: ['a|b|c', 'd']
# 6. join()
# Nối các phần tử trong một iterable bằng một chuỗi phân cách
ky_tu_noi = '-'.join('HELLO') # Nối các ký tự của chuỗi 'HELLO' bằng '-'
print(ky_tu_noi) # Kết quả: 'H-E-L-L-O'
danh_sach_noi = ['Python', 'is', 'fun']
tu_noi = ' '.join(danh_sach_noi) # Nối các phần tử của danh sách bằng khoảng trắng
print(tu_noi) # Kết quả: 'Python is fun'
# 7. replace()
chuoi_ban_dau = 'Tôi thích lập trình Python. Python rất mạnh mẽ.'
# Thay thế 'Python' bằng 'Java'
chuoi_da_thay = chuoi_ban_dau.replace('Python', 'Java')
print(chuoi_da_thay) # Kết quả: 'Tôi thích lập trình Java. Java rất mạnh mẽ.'
# Thay thế với giới hạn số lần
chuoi_gioi_han = 'apple banana apple orange'
chuoi_moi_gioi_han = chuoi_gioi_han.replace('apple', 'grape', 1) # Chỉ thay thế lần đầu tiên
print(chuoi_moi_gioi_han) # Kết quả: 'grape banana apple orange'
# 8. isdigit()
print('12345'.isdigit()) # Kết quả: True
print('12a34'.isdigit()) # Kết quả: False
print('12.3'.isdigit()) # Kết quả: False (chứa dấu chấm)
2.3.3 Các thao tác tham khảo thêm
thong_bao = 'Tìm kiếm từ khóa trong chuỗi'
# 1. find(), rfind(), index(), rindex(), count()
# find(): Tìm chỉ mục xuất hiện đầu tiên của chuỗi con, trả về -1 nếu không tìm thấy
print(thong_bao.find('khóa')) # Kết quả: 9
print(thong_bao.find('abc')) # Kết quả: -1
# index(): Giống find(), nhưng báo lỗi ValueError nếu không tìm thấy
# thong_bao.index('abc') # Báo lỗi ValueError
# count(): Đếm số lần xuất hiện của chuỗi con
print("banana".count('a')) # Kết quả: 3
print("hello world".count('l', 0, 5)) # Đếm 'l' trong "hell" (chỉ mục 0-4), Kết quả: 2
ten_tai_khoan = 'user'
# 2. center(), ljust(), rjust(), zfill()
# center(): Căn giữa chuỗi trong một chiều rộng nhất định
print(ten_tai_khoan.center(20, '*')) # Kết quả: '********user********'
# ljust(): Căn trái
print(ten_tai_khoan.ljust(10, '-')) # Kết quả: 'user------'
# rjust(): Căn phải
print(ten_tai_khoan.rjust(10, '-')) # Kết quả: '------user'
# zfill(): Đệm bằng số 0 ở bên trái
print(ten_tai_khoan.zfill(8)) # Kết quả: '0000user'
# 3. expandtabs()
chuoi_tab = 'item1\titem2\titem3'
print(chuoi_tab) # Kết quả có thể khác tùy môi trường, ví dụ: 'item1 item2 item3'
print(chuoi_tab.expandtabs(2)) # Thay đổi kích thước tab thành 2 khoảng trắng: 'item1 item2 item3'
# 4. capitalize(), swapcase(), title()
chuoi_van_ban = 'hôm nay thời tiết thật đẹp!'
print(chuoi_van_ban.capitalize()) # Kết quả: 'Hôm nay thời tiết thật đẹp!' (chỉ chữ cái đầu tiên viết hoa)
chuoi_hoa_thuong = 'pHyThOn Is AWESOME'
print(chuoi_hoa_thuong.swapcase()) # Kết quả: 'PhYtHoN iS awesome' (đổi hoa thành thường, thường thành hoa)
chuoi_tieu_de = 'học python thật vui'
print(chuoi_tieu_de.title()) # Kết quả: 'Học Python Thật Vui' (chữ cái đầu mỗi từ viết hoa)
# 5. Các phương thức kiểm tra số (is...numeric)
# Trong Python 3:
so_byte = b'123' # bytes
so_unicode = '456' # unicode (mặc định trong Python 3)
so_han = '一二三' # số tiếng Hán
so_la_ma = 'IV' # số La Mã
# isdigit(): Kiểm tra xem chuỗi có chỉ chứa các chữ số (0-9) không
print(so_byte.isdigit()) # Kết quả: True
print(so_unicode.isdigit()) # Kết quả: True
print(so_han.isdigit()) # Kết quả: False
print(so_la_ma.isdigit()) # Kết quả: False
# isdecimal(): Chỉ dành cho unicode, kiểm tra các chữ số thập phân
print(so_unicode.isdecimal()) # Kết quả: True
print(so_han.isdecimal()) # Kết quả: False
print(so_la_ma.isdecimal()) # Kết quả: False
# isnumeric(): Kiểm tra xem chuỗi có chứa các ký tự số (bao gồm số tiếng Hán, La Mã) không
print(so_unicode.isnumeric()) # Kết quả: True
print(so_han.isnumeric()) # Kết quả: True
print(so_la_ma.isnumeric()) # Kết quả: True
# Các phương thức này KHÔNG kiểm tra được số thực
so_thuc_chuoi = '12.3'
print(so_thuc_chuoi.isdigit()) # Kết quả: False
print(so_thuc_chuoi.isdecimal()) # Kết quả: False
print(so_thuc_chuoi.isnumeric()) # Kết quả: False
# Tóm tắt:
# isdigit thường dùng nhất cho bytes và unicode (số Ả Rập).
# isnumeric dùng khi cần kiểm tra cả các dạng số khác như số tiếng Hán, La Mã.
# 6. Các phương thức kiểm tra khác (is...)
chuoi_test = 'python123'
print(chuoi_test.isalnum()) # Kết quả: True (chứa chữ cái và số)
print(chuoi_test.isalpha()) # Kết quả: False (chứa cả số)
bien_hop_le = 'my_variable'
print(bien_hop_le.isidentifier()) # Kết quả: True (có thể là tên biến hợp lệ)
print('lowercase'.islower()) # Kết quả: True
print('UPPERCASE'.isupper()) # Kết quả: True
print(' '.isspace()) # Kết quả: True (chỉ chứa khoảng trắng)
print('This Is A Title'.istitle()) # Kết quả: True (mỗi từ đều viết hoa chữ cái đầu)
3. Kiểu Danh sách (list)
3.1 Định nghĩa
Danh sách là một tập hợp các giá trị (phần tử) được sắp xếp, có thể thay đổi và chứa bất kỳ kiểu dữ liệu nào, được đặt trong dấu ngoặc vuông [] và phân cách bởi dấu phẩy.
# Định nghĩa một danh sách
danh_sach_don_hang = [101, 'áo thun', 25.5, ['đen', 'L']] # Thực chất: list([101, 'áo thun', ...])
3.2 Chuyển đổi kiểu
Hàm list() có thể chuyển đổi bất kỳ kiểu dữ liệu nào có thể lặp (iterable) thành danh sách, duyệt qua từng phần tử và thêm chúng vào danh sách mới.
# Từ chuỗi sang danh sách
print(list('data')) # Kết quả: ['d', 'a', 't', 'a']
# Từ tuple sang danh sách
print(list((1, 2, 3))) # Kết quả: [1, 2, 3]
# Từ từ điển sang danh sách (chỉ lấy các khóa)
print(list({"ma_sp": "A001", "gia": 100})) # Kết quả: ['ma_sp', 'gia']
# Từ tập hợp sang danh sách (thứ tự không đảm bảo)
print(list({5, 6, 7})) # Kết quả: [5, 6, 7] (thứ tự có thể khác)
3.3 Sử dụng
3.3.1 Các thao tác quan trọng
danh_sach_sp = ['laptop', 'chuột', 'bàn phím', 500, True]
# 1. Truy cập và thay đổi giá trị bằng chỉ mục
# Truy cập phần tử (chỉ mục dương/âm)
print(danh_sach_sp[0]) # Kết quả: 'laptop'
print(danh_sach_sp[-2]) # Kết quả: 500
# Thay đổi giá trị (danh sách là có thể thay đổi)
danh_sach_sp[1] = 'tai nghe'
print(danh_sach_sp) # Kết quả: ['laptop', 'tai nghe', 'bàn phím', 500, True]
# 2. Cắt danh sách (Slicing)
print(danh_sach_sp[0:3]) # Kết quả: ['laptop', 'tai nghe', 'bàn phím']
print(danh_sach_sp[::2]) # Kết quả: ['laptop', 'bàn phím', True]
# 3. Độ dài danh sách (len)
print(len(danh_sach_sp)) # Kết quả: 5
# 4. Kiểm tra thành viên (in và not in)
print('laptop' in danh_sach_sp) # Kết quả: True
print('màn hình' not in danh_sach_sp) # Kết quả: True
# 5. Thêm phần tử
# append(): Thêm một phần tử vào cuối danh sách
danh_sach_sp.append('ổ cứng')
print(danh_sach_sp) # Kết quả: ['laptop', 'tai nghe', 'bàn phím', 500, True, 'ổ cứng']
# extend(): Thêm nhiều phần tử từ một iterable vào cuối danh sách
danh_sach_sp.extend(['webcam', 'mic'])
print(danh_sach_sp) # Kết quả: ['laptop', 'tai nghe', 'bàn phím', 500, True, 'ổ cứng', 'webcam', 'mic']
# insert(): Chèn phần tử vào vị trí chỉ định
danh_sach_sp.insert(1, 'sạc') # Chèn 'sạc' vào chỉ mục 1
print(danh_sach_sp) # Kết quả: ['laptop', 'sạc', 'tai nghe', 'bàn phím', 500, True, 'ổ cứng', 'webcam', 'mic']
# 6. Xóa phần tử
# del: Xóa phần tử tại chỉ mục hoặc cắt lát
del danh_sach_sp[0] # Xóa phần tử đầu tiên
print(danh_sach_sp)
# pop(): Xóa và trả về phần tử cuối cùng (hoặc tại chỉ mục chỉ định)
phan_tu_cuoi = danh_sach_sp.pop() # Xóa 'mic'
print(f"Phần tử bị xóa: {phan_tu_cuoi}, Danh sách mới: {danh_sach_sp}")
phan_tu_tai_chi_muc = danh_sach_sp.pop(0) # Xóa 'sạc'
print(f"Phần tử bị xóa: {phan_tu_tai_chi_muc}, Danh sách mới: {danh_sach_sp}")
# remove(): Xóa phần tử đầu tiên có giá trị khớp
danh_sach_gia = [10, 20, 30, 20, 40]
danh_sach_gia.remove(20) # Xóa số 20 đầu tiên
print(danh_sach_gia) # Kết quả: [10, 30, 20, 40]
# 7. reverse(): Đảo ngược thứ tự các phần tử trong danh sách
danh_sach_so = [1, 2, 3, 4, 5]
danh_sach_so.reverse()
print(danh_sach_so) # Kết quả: [5, 4, 3, 2, 1]
# 8. sort(): Sắp xếp các phần tử trong danh sách
# Lưu ý: Các phần tử phải cùng kiểu và có thể so sánh được.
danh_sach_diem = [85, 92, 78, 95, 88]
danh_sach_diem.sort() # Mặc định sắp xếp tăng dần
print(danh_sach_diem) # Kết quả: [78, 85, 88, 92, 95]
danh_sach_diem.sort(reverse=True) # Sắp xếp giảm dần
print(danh_sach_diem) # Kết quả: [95, 92, 88, 85, 78]
# Sắp xếp chuỗi (dựa trên thứ tự ASCII/Unicode)
danh_sach_chuoi = ['apple', 'Banana', 'cat', 'Dog']
danh_sach_chuoi.sort()
print(danh_sach_chuoi) # Kết quả: ['Banana', 'Dog', 'apple', 'cat'] (chữ hoa đứng trước chữ thường)
# 9. Duyệt danh sách
for item in danh_sach_sp:
print(item)
3.3.2 Các thao tác tham khảo thêm
data_numbers = [10, 20, 30, 40, 50]
# Đảo ngược danh sách bằng cắt lát (tạo danh sách mới)
dao_nguoc_moi = data_numbers[::-1]
print(dao_nguoc_moi) # Kết quả: [50, 40, 30, 20, 10]
4. Kiểu Bộ giá trị (tuple)
4.1 Mục đích
Tuple tương tự như danh sách ở chỗ chúng có thể lưu trữ nhiều phần tử thuộc các kiểu dữ liệu khác nhau. Tuy nhiên, điểm khác biệt chính là tuple là bất biến (immutable) – một khi đã tạo, các phần tử của nó không thể bị thay đổi, thêm vào hay xóa đi. Chúng được dùng để lưu trữ các tập hợp giá trị cố định không cần thay đổi.
4.2 Định nghĩa
Tuple được định nghĩa bằng cách đặt các phần tử trong dấu ngoặc đơn (), phân cách bởi dấu phẩy.
# Định nghĩa một tuple
thong_tin_khach_hang = ("Alice", 28, "Hà Nội") # Thực chất: tuple("Alice", 28, "Hà Nội")
# Lưu ý quan trọng: Nếu tuple chỉ có một phần tử, PHẢI thêm dấu phẩy sau phần tử đó
tuple_don = ("Python",) # Đây là một tuple
not_a_tuple = ("Python") # Đây chỉ là một chuỗi trong ngoặc đơn
print(type(tuple_don)) # Kết quả: <class 'tuple'>
print(type(not_a_tuple)) # Kết quả: <class 'str'>
4.3 Chuyển đổi kiểu
Hàm tuple() có thể chuyển đổi bất kỳ kiểu dữ liệu nào có thể lặp (iterable) thành một tuple.
# Từ chuỗi sang tuple
print(tuple('code')) # Kết quả: ('c', 'o', 'd', 'e')
# Từ danh sách sang tuple
print(tuple([100, 200, 300])) # Kết quả: (100, 200, 300)
# Từ từ điển sang tuple (chỉ lấy các khóa)
print(tuple({"sp_id": "P001", "so_luong": 10})) # Kết quả: ('sp_id', 'so_luong')
4.4 Sử dụng
du_lieu_nguoi_dung = (101, 'Minh', 'minh@example.com', 'active', 2023)
# 1. Truy cập phần tử bằng chỉ mục (chỉ đọc, không thay đổi)
print(du_lieu_nguoi_dung[1]) # Kết quả: 'Minh'
print(du_lieu_nguoi_dung[-1]) # Kết quả: 2023
# du_lieu_nguoi_dung[0] = 102 # Sẽ báo lỗi TypeError
# 2. Cắt tuple (Slicing)
print(du_lieu_nguoi_dung[0:3]) # Kết quả: (101, 'Minh', 'minh@example.com')
# 3. Độ dài tuple (len)
print(len(du_lieu_nguoi_dung)) # Kết quả: 5
# 4. Kiểm tra thành viên (in và not in)
print('Minh' in du_lieu_nguoi_dung) # Kết quả: True
print('inactive' not in du_lieu_nguoi_dung) # Kết quả: True
# 5. Duyệt tuple (Loop)
for item in du_lieu_nguoi_dung:
print(item)
5. Kiểu Từ điển (dict)
5.1 Định nghĩa
Từ điển là một tập hợp các cặp khóa-giá trị (key-value) không có thứ tự, có thể thay đổi. Mỗi khóa phải là duy nhất và là một kiểu dữ liệu bất biến (thường là chuỗi hoặc số), trong khi giá trị có thể là bất kỳ kiểu dữ liệu nào. Từ điển được định nghĩa bằng dấu ngoặc nhọn {}.
# Định nghĩa từ điển
ho_so_nhan_vien = {'ten': 'Quang', 'tuoi': 35, 'chuc_vu': 'Kỹ sư'} # Thực chất: dict({'ten': ..., 'tuoi': ...})
# Cách khác để định nghĩa từ điển (khi khóa là chuỗi hợp lệ)
cau_hinh_ung_dung = dict(host='localhost', port=8000, debug=True)
print(cau_hinh_ung_dung) # Kết quả: {'host': 'localhost', 'port': 8000, 'debug': True}
5.2 Chuyển đổi kiểu
# Chuyển đổi từ danh sách các cặp khóa-giá trị (tuple hoặc list)
tham_so = dict([['ma_sp', 'B123'], ('so_luong', 10)])
print(tham_so) # Kết quả: {'ma_sp': 'B123', 'so_luong': 10}
# Sử dụng fromkeys(): Tạo từ điển với các khóa từ một iterable và gán một giá trị mặc định
cau_hinh_mac_dinh = {}.fromkeys(('user', 'password', 'role'), None)
print(cau_hinh_mac_dinh) # Kết quả: {'user': None, 'password': None, 'role': None}
5.3 Sử dụng
5.3.1 Các thao tác quan trọng
chi_tiet_san_pham = {
'ma_sp': 'P001',
'ten_sp': 'Điện thoại X',
'gia': 799.99,
'thong_so': ['RAM 8GB', 'SSD 256GB']
}
# 1. Truy cập và cập nhật giá trị bằng khóa
# Truy cập giá trị
print(chi_tiet_san_pham['ten_sp']) # Kết quả: 'Điện thoại X'
print(chi_tiet_san_pham['thong_so'][0]) # Kết quả: 'RAM 8GB'
# Thêm cặp khóa-giá trị mới
chi_tiet_san_pham['mau_sac'] = 'đen'
print(chi_tiet_san_pham)
# Sửa đổi giá trị hiện có
chi_tiet_san_pham['gia'] = 749.99
print(chi_tiet_san_pham)
# 2. Độ dài từ điển (len)
print(len(chi_tiet_san_pham)) # Kết quả: 5 (bao gồm cả 'mau_sac')
# 3. Kiểm tra thành viên (in và not in) - kiểm tra khóa
print('ten_sp' in chi_tiet_san_pham) # Kết quả: True
print('nha_sx' not in chi_tiet_san_pham) # Kết quả: True
# 4. Xóa phần tử (pop)
gia_cu = chi_tiet_san_pham.pop('gia') # Xóa khóa 'gia' và trả về giá trị của nó
print(f"Giá cũ: {gia_cu}, Từ điển mới: {chi_tiet_san_pham}")
# 5. Lấy các khóa, giá trị, cặp khóa-giá trị
# keys(): Lấy tất cả các khóa
print(chi_tiet_san_pham.keys()) # Kết quả: dict_keys(['ma_sp', 'ten_sp', 'thong_so', 'mau_sac'])
# values(): Lấy tất cả các giá trị
print(chi_tiet_san_pham.values()) # Kết quả: dict_values(['P001', 'Điện thoại X', ['RAM 8GB', 'SSD 256GB'], 'đen'])
# items(): Lấy tất cả các cặp khóa-giá trị dưới dạng tuple
print(chi_tiet_san_pham.items()) # Kết quả: dict_items([('ma_sp', 'P001'), ('ten_sp', 'Điện thoại X'), ...])
# 6. Duyệt từ điển
# Duyệt mặc định (lấy khóa)
for key in chi_tiet_san_pham:
print(f"Khóa: {key}, Giá trị: {chi_tiet_san_pham[key]}")
# Duyệt qua các khóa
for k in chi_tiet_san_pham.keys():
print(k)
# Duyệt qua các giá trị
for v in chi_tiet_san_pham.values():
print(v)
# Duyệt qua các cặp khóa-giá trị
for k, v in chi_tiet_san_pham.items():
print(f"Khóa: {k}, Giá trị: {v}")
5.3.2 Các thao tác nâng cao
cai_dat = {'database': 'mydb', 'user': 'admin', 'password': '123'}
# 1. get()
# Truy cập giá trị một cách an toàn (không báo lỗi nếu khóa không tồn tại)
db_user = cai_dat.get('user')
print(db_user) # Kết quả: 'admin'
non_existent_key = cai_dat.get('host')
print(non_existent_key) # Kết quả: None (mặc định nếu khóa không tồn tại)
default_host = cai_dat.get('host', 'localhost')
print(default_host) # Kết quả: 'localhost' (có thể thiết lập giá trị mặc định)
# 2. pop()
# Xóa một cặp khóa-giá trị theo khóa và trả về giá trị
removed_pass = cai_dat.pop('password')
print(f"Mật khẩu đã xóa: {removed_pass}, Cài đặt mới: {cai_dat}")
# 3. popitem()
# Xóa một cặp khóa-giá trị ngẫu nhiên (hoặc cuối cùng trong Python 3.7+) và trả về nó dưới dạng tuple
random_item = cai_dat.popitem()
print(f"Cặp ngẫu nhiên đã xóa: {random_item}, Cài đặt mới: {cai_dat}")
# 4. update()
# Cập nhật từ điển bằng cách thêm hoặc sửa đổi các cặp khóa-giá trị từ một từ điển khác
thong_tin_them = {'user': 'root', 'port': 5432}
cai_dat.update(thong_tin_them)
print(cai_dat) # Kết quả: {'database': 'mydb', 'user': 'root', 'port': 5432}
# 5. fromkeys()
# Tạo từ điển mới với các khóa từ iterable và một giá trị mặc định
trang_thai_nguoi_dung = dict.fromkeys(['alice', 'bob', 'charlie'], 'offline')
print(trang_thai_nguoi_dung) # Kết quả: {'alice': 'offline', 'bob': 'offline', 'charlie': 'offline'}
# 6. setdefault()
# Nếu khóa tồn tại, trả về giá trị của khóa đó và không làm gì.
# Nếu khóa không tồn tại, thêm cặp khóa-giá trị mới và trả về giá trị mới đó.
cau_hinh_web = {'theme': 'dark'}
# Khóa 'theme' tồn tại
current_theme = cau_hinh_web.setdefault('theme', 'light')
print(f"Theme hiện tại: {current_theme}, Cấu hình: {cau_hinh_web}") # Kết quả: 'dark', {'theme': 'dark'}
# Khóa 'language' không tồn tại
new_lang = cau_hinh_web.setdefault('language', 'vi')
print(f"Ngôn ngữ mới: {new_lang}, Cấu hình: {cau_hinh_web}") # Kết quả: 'vi', {'theme': 'dark', 'language': 'vi'}
6. Kiểu Tập hợp (set)
6.1 Mục đích
Tập hợp là một tập hợp các phần tử không có thứ tự và không trùng lặp, có thể thay đổi. Chúng được sử dụng chủ yếu để loại bỏ các phần tử trùng lặp và thực hiện các phép toán tập hợp (ví dụ: hợp, giao, hiệu).
6.2 Định nghĩa
Tập hợp được định nghĩa bằng cách đặt các phần tử trong dấu ngoặc nhọn {}, phân cách bởi dấu phẩy. Các phần tử của tập hợp phải là các kiểu dữ liệu bất biến (ví dụ: số, chuỗi, tuple).
# Định nghĩa một tập hợp
cac_so_chan = {2, 4, 6, 8} # Thực chất: set({2, 4, 6, 8})
# Lưu ý 1: Tập hợp không có chỉ mục hoặc khóa để truy cập từng phần tử cụ thể
# print(cac_so_chan[0]) # Sẽ báo lỗi TypeError
# Lưu ý 2: Cách định nghĩa tập hợp rỗng và từ điển rỗng
tu_dien_rong = {} # Đây là từ điển rỗng
tap_hop_rong = set() # Đây là tập hợp rỗng
6.3 Chuyển đổi kiểu
Hàm set() có thể chuyển đổi bất kỳ kiểu dữ liệu nào có thể lặp (iterable) thành tập hợp. Các phần tử trùng lặp sẽ tự động bị loại bỏ.
# Từ danh sách sang tập hợp
print(set([1, 2, 2, 3, 4, 4])) # Kết quả: {1, 2, 3, 4}
# Từ chuỗi sang tập hợp (mỗi ký tự là một phần tử, thứ tự không đảm bảo)
print(set('abracadabra')) # Kết quả: {'r', 'b', 'c', 'a', 'd'}
# Từ tuple sang tập hợp
print(set(('red', 'green', 'blue'))) # Kết quả: {'blue', 'green', 'red'}
6.4 Sử dụng
6.4.1 Các phép toán tập hợp
Giả sử chúng ta có hai tập hợp biểu diễn sở thích của hai người:
so_thich_an = {"đọc sách", "xem phim", "chơi game", "đi bộ"}
so_thich_binh = {"xem phim", "chơi thể thao", "đi bộ", "nấu ăn"}
# 1. Hợp (Union) |: Tất cả các sở thích của cả hai người (không trùng lặp)
print(so_thich_an | so_thich_binh)
# Kết quả: {'đi bộ', 'chơi game', 'xem phim', 'chơi thể thao', 'đọc sách', 'nấu ăn'}
# 2. Giao (Intersection) &: Các sở thích chung của cả hai người
print(so_thich_an & so_thich_binh)
# Kết quả: {'đi bộ', 'xem phim'}
# 3. Hiệu (Difference) -: Sở thích riêng của từng người
print(so_thich_an - so_thich_binh) # Sở thích chỉ của An
# Kết quả: {'đọc sách', 'chơi game'}
print(so_thich_binh - so_thich_an) # Sở thích chỉ của Bình
# Kết quả: {'chơi thể thao', 'nấu ăn'}
# 4. Hiệu đối xứng (Symmetric Difference) ^: Sở thích độc quyền của mỗi người (không bao gồm sở thích chung)
print(so_thich_an ^ so_thich_binh)
# Kết quả: {'nấu ăn', 'chơi thể thao', 'đọc sách', 'chơi game'}
# 5. Kiểm tra bằng nhau (==)
print(so_thich_an == so_thich_binh) # Kết quả: False
# 6. Tập cha (Superset) >, >=: Một tập hợp có chứa tập hợp kia không?
print({1, 2, 3, 4} > {1, 2}) # Kết quả: True (lớn hơn hẳn)
print({1, 2, 3} >= {1, 2, 3}) # Kết quả: True (lớn hơn hoặc bằng)
# 7. Tập con (Subset) <, <=: Một tập hợp có là con của tập hợp kia không?
print({1, 2} < {1, 2, 3}) # Kết quả: True (nhỏ hơn hẳn)
print({1, 2, 3} <= {1, 2, 3}) # Kết quả: True (nhỏ hơn hoặc bằng)
6.4.2 Loại bỏ trùng lặp
Tập hợp là công cụ hiệu quả để loại bỏ các phần tử trùng lặp, nhưng có một số hạn chế:
- Chỉ có thể loại bỏ trùng lặp cho các kiểu dữ liệu bất biến.
- Thứ tự các phần tử không được bảo toàn sau khi chuyển đổi sang tập hợp và ngược lại.
danh_sach_voi_trung = ['a', 'b', 1, 'a', 'c', 1, 'b']
tap_hop_tu_danh_sach = set(danh_sach_voi_trung)
print(tap_hop_tu_danh_sach) # Kết quả: {'b', 1, 'c', 'a'} (thứ tự có thể thay đổi)
danh_sach_da_loc = list(tap_hop_tu_danh_sach)
print(danh_sach_da_loc) # Kết quả: [1, 'c', 'a', 'b'] (thứ tự ban đầu không được giữ)
# Để loại bỏ trùng lặp cho các kiểu dữ liệu có thể thay đổi (ví dụ: từ điển trong danh sách)
# hoặc để giữ nguyên thứ tự, cần triển khai logic thủ công:
danh_sach_nguoi = [
{'ten': 'Minh', 'tuoi': 25},
{'ten': 'An', 'tuoi': 30},
{'ten': 'Minh', 'tuoi': 25},
{'ten': 'Binh', 'tuoi': 28},
{'ten': 'An', 'tuoi': 30},
]
danh_sach_duy_nhat = []
for nguoi in danh_sach_nguoi:
if nguoi not in danh_sach_duy_nhat:
danh_sach_duy_nhat.append(nguoi)
print(danh_sach_duy_nhat)
# Kết quả:
# [{'ten': 'Minh', 'tuoi': 25},
# {'ten': 'An', 'tuoi': 30},
# {'ten': 'Binh', 'tuoi': 28}]
6.4.3 Các thao tác khác
tap_hop_chu = {'X', 'Y', 'Z'}
# 1. Độ dài (len)
print(len(tap_hop_chu)) # Kết quả: 3
# 2. Kiểm tra thành viên (in và not in)
print('Y' in tap_hop_chu) # Kết quả: True
# 3. Duyệt tập hợp (Loop)
for phan_tu in tap_hop_chu:
print(phan_tu)
# Kết quả: (thứ tự không đảm bảo)
# Y
# X
# Z
6.5 Bài tập thực hành
Có hai tập hợp tên học viên đăng ký khóa học Python và Linux:
hoc_vien_python = {'minh', 'an', 'binh', 'phong', 'long', 'hoa'}
hoc_vien_linux = {'mai', 'thuy', 'long', 'phong'}
# 1. Tìm tập hợp các học viên đăng ký cả hai khóa Python và Linux.
print(hoc_vien_python & hoc_vien_linux) # Kết quả: {'phong', 'long'}
# 2. Tìm tập hợp tất cả các học viên đã đăng ký (không trùng lặp).
print(hoc_vien_python | hoc_vien_linux) # Kết quả: {'hoa', 'mai', 'an', 'thuy', 'binh', 'phong', 'long', 'minh'}
# 3. Tìm tập hợp các học viên chỉ đăng ký khóa Python.
print(hoc_vien_python - hoc_vien_linux) # Kết quả: {'hoa', 'an', 'minh', 'binh'}
# 4. Tìm tập hợp các học viên không đăng ký đồng thời cả hai khóa.
print(hoc_vien_python ^ hoc_vien_linux) # Kết quả: {'hoa', 'mai', 'an', 'thuy', 'binh', 'minh'}
7. Kiểu dữ liệu có thể thay đổi (Mutable) và không thể thay đổi (Immutable)
Trong Python, các kiểu dữ liệu được chia thành hai loại chính: có thể thay đổi và không thể thay đổi. Sự khác biệt nằm ở việc liệu giá trị của đối tượng có thể được sửa đổi sau khi nó được tạo hay không.
- Kiểu dữ liệu có thể thay đổi (Mutable): Khi giá trị của đối tượng thay đổi, địa chỉ bộ nhớ (ID) của đối tượng đó vẫn giữ nguyên. Điều này chứng tỏ chúng ta đang thay đổi chính đối tượng gốc.
- Kiểu dữ liệu không thể thay đổi (Immutable): Khi giá trị của đối tượng thay đổi, địa chỉ bộ nhớ (ID) của đối tượng cũng thay đổi. Điều này có nghĩa là một đối tượng mới đã được tạo ra thay vì sửa đổi đối tượng gốc.
Số (int, float)
so_nguyen = 100
print(f"ID ban đầu: {id(so_nguyen)}") # Ví dụ: ID ban đầu: 12345678
so_nguyen = 200 # Gán lại giá trị
print(f"ID sau khi thay đổi: {id(so_nguyen)}") # Ví dụ: ID sau khi thay đổi: 87654321 (ID thay đổi)
# Số nguyên là kiểu dữ liệu không thể thay đổi.
Chuỗi (str)
ten_cu = "Hùng"
print(f"ID ban đầu: {id(ten_cu)}") # Ví dụ: ID ban đầu: 11223344
ten_moi = "Thắng"
print(f"ID sau khi gán mới: {id(ten_moi)}") # Ví dụ: ID sau khi gán mới: 55667788 (ID thay đổi)
# Chuỗi là kiểu dữ liệu không thể thay đổi.
Danh sách (list)
danh_sach_diem = [70, 80, 90]
print(f"ID ban đầu: {id(danh_sach_diem)}") # Ví dụ: ID ban đầu: 99887766
danh_sach_diem[1] = 85 # Sửa đổi một phần tử
print(f"ID sau khi sửa phần tử: {id(danh_sach_diem)}") # Ví dụ: ID sau khi sửa phần tử: 99887766 (ID không thay đổi)
danh_sach_diem.append(95) # Thêm một phần tử
print(f"ID sau khi thêm phần tử: {id(danh_sach_diem)}") # Ví dụ: ID sau khi thêm phần tử: 99887766 (ID không thay đổi)
# Danh sách là kiểu dữ liệu có thể thay đổi.
Bộ giá trị (tuple)
tuple_data = (1, 'text', [10, 20])
print(f"ID của tuple: {id(tuple_data)}") # Ví dụ: ID của tuple: 112233
# tuple_data[0] = 5 # Báo lỗi TypeError: tuple là bất biến
# tuple_data.append(3) # Báo lỗi TypeError: tuple là bất biến
# Tuy nhiên, nếu tuple chứa một phần tử là kiểu có thể thay đổi, phần tử đó CÓ THỂ được sửa đổi.
# Địa chỉ của phần tử trong tuple:
print(f"ID của phần tử danh sách trong tuple: {id(tuple_data[2])}") # Ví dụ: ID: 445566
tuple_data[2][0] = 100 # Sửa đổi phần tử trong danh sách con
print(tuple_data) # Kết quả: (1, 'text', [100, 20])
print(f"ID của phần tử danh sách sau sửa đổi: {id(tuple_data[2])}") # Ví dụ: ID: 445566 (ID không thay đổi)
# Tuple tự thân là bất biến (không thể thay đổi cấu trúc hoặc tham chiếu các phần tử cấp cao nhất),
# nhưng các phần tử bên trong nó CÓ THỂ thay đổi nếu chúng là kiểu dữ liệu mutable.
Từ điển (dict)
thong_tin_cau_hinh = {'env': 'dev', 'debug': True}
print(f"ID ban đầu: {id(thong_tin_cau_hinh)}") # Ví dụ: ID ban đầu: 778899
thong_tin_cau_hinh['debug'] = False # Sửa đổi giá trị
print(f"ID sau khi sửa giá trị: {id(thong_tin_cau_hinh)}") # Ví dụ: ID sau khi sửa giá trị: 778899 (ID không thay đổi)
thong_tin_cau_hinh['version'] = '1.0' # Thêm cặp khóa-giá trị mới
print(f"ID sau khi thêm cặp: {id(thong_tin_cau_hinh)}") # Ví dụ: ID sau khi thêm cặp: 778899 (ID không thay đổi)
# Từ điển là kiểu dữ liệu có thể thay đổi.