Skip to content

💬 4.3 Kiểu chuỗi (str)

📖 Giới thiệu

Chuỗi (string) là kiểu dữ liệu để lưu trữ văn bản trong Python. Từ tên người, địa chỉ email đến nội dung trang web, chuỗi có mặt ở khắp mọi nơi trong lập trình. Hiểu cách làm việc với chuỗi là kỹ năng thiết yếu cho mọi lập trình viên Python.

Mục tiêu bài học:

  • Hiểu cách tạo và lưu trữ chuỗi
  • Thành thạo các thao tác cơ bản với chuỗi
  • Biết cách định dạng và xử lý chuỗi
  • Sử dụng chuỗi trong các ứng dụng thực tế

🔧 Cú pháp

Cách tạo chuỗi:

python
# Nháy đơn
chuoi_1 = 'Hello Python'

# Nháy đôi  
chuoi_2 = "Xin chào Python"

# Triple quotes (nhiều dòng)
chuoi_nhieu_dong = """
Đây là chuỗi
có nhiều dòng
"""

# Raw string (không xử lý escape)
duong_dan = r'C:\Users\name\Documents'

Thao tác chuỗi cơ bản:

python
text = "Python Programming"

# Độ dài
len(text)           # 18

# Truy cập ký tự
text[0]             # 'P'
text[-1]            # 'g'

# Cắt chuỗi (slicing)
text[0:6]           # 'Python'
text[7:]            # 'Programming'

# Kiểm tra
'Python' in text    # True

🔬 Phân tích & Giải thích chi tiết

1. 📝 Cách tạo chuỗi

Nháy đơn vs nháy đôi:

python
# Tương đương nhau
ten_1 = 'Python'
ten_2 = "Python"

# Khi cần dùng nháy trong chuỗi
cau_noi = "Tôi học 'Python' mỗi ngày"
cau_noi_2 = 'Anh ấy nói: "Python rất tuyệt!"'

# Hoặc dùng escape character
cau_noi_3 = "Anh ấy nói: \"Python rất tuyệt!\""

Triple quotes cho chuỗi nhiều dòng:

python
# Thơ hoặc văn bản dài
bai_tho = """
Lập trình viên tôi,
Code Python mỗi ngày,
Bug ít đi rồi!
"""

# SQL query
sql = """
SELECT ten, tuoi, lop
FROM hoc_sinh 
WHERE diem_tb > 8.0
ORDER BY diem_tb DESC
"""

Raw string:

python
# Thường dùng cho regex và đường dẫn
duong_dan_windows = r'C:\Users\Python\Documents\file.txt'
regex_pattern = r'\d{3}-\d{3}-\d{4}'  # Pattern số điện thoại

# So sánh với chuỗi thường
normal_string = 'C:\\Users\\Python\\Documents\\file.txt'
print(duong_dan_windows == normal_string)  # True

2. 🔍 Truy cập và cắt chuỗi

Indexing (truy cập ký tự):

python
text = "PYTHON"
#       012345  (index dương)
#      -654321  (index âm)

print(text[0])   # 'P' (ký tự đầu)
print(text[5])   # 'N' (ký tự cuối)
print(text[-1])  # 'N' (ký tự cuối, cách khác)
print(text[-6])  # 'P' (ký tự đầu, cách khác)

Slicing (cắt chuỗi):

python
text = "Python Programming"
#       0123456789...

# Cú pháp: [start:stop:step]
print(text[0:6])     # 'Python'
print(text[7:])      # 'Programming'
print(text[:6])      # 'Python'
print(text[::2])     # 'Pto rgamn' (cách 2 ký tự)
print(text[::-1])    # 'gnimmargorP nohtyP' (đảo ngược)

3. 🔧 Các phương thức chuỗi quan trọng

Tìm kiếm và kiểm tra:

python
text = "Python Programming Language"

# Tìm kiếm
text.find('Python')        # 0 (vị trí đầu tiên)
text.find('Java')          # -1 (không tìm thấy)
text.count('g')            # 3 (số lần xuất hiện)

# Kiểm tra
'Python' in text           # True
text.startswith('Python')  # True
text.endswith('Language')  # True

Thay đổi case:

python
text = "Python Programming"

text.upper()        # 'PYTHON PROGRAMMING'
text.lower()        # 'python programming'
text.title()        # 'Python Programming'
text.capitalize()   # 'Python programming'
text.swapcase()     # 'pYTHON pROGRAMMING'

Xóa khoảng trắng:

python
text = "  Python Programming  "

text.strip()        # 'Python Programming'
text.lstrip()       # 'Python Programming  '
text.rstrip()       # '  Python Programming'

Tách và nối chuỗi:

python
# Tách chuỗi
cau = "Python,Java,C++,JavaScript"
ngon_ngu = cau.split(',')  # ['Python', 'Java', 'C++', 'JavaScript']

ho_ten = "Nguyễn Văn An"
ho_ten.split()             # ['Nguyễn', 'Văn', 'An']

# Nối chuỗi
danh_sach = ['Python', 'Java', 'C++']
ket_qua = ', '.join(danh_sach)  # 'Python, Java, C++'

4. 🎨 Định dạng chuỗi

F-string (khuyến nghị):

python
ten = "Minh"
tuoi = 25
diem = 8.75

# F-string
thong_tin = f"Tên: {ten}, Tuổi: {tuoi}, Điểm: {diem:.1f}"
print(thong_tin)  # Tên: Minh, Tuổi: 25, Điểm: 8.8

Method .format():

python
# Với index
template = "Tên: {0}, Tuổi: {1}, Điểm: {2:.1f}"
ket_qua = template.format(ten, tuoi, diem)

# Với tên
template = "Tên: {ten}, Tuổi: {tuoi}, Điểm: {diem:.1f}"
ket_qua = template.format(ten=ten, tuoi=tuoi, diem=diem)

💻 Ví dụ minh họa

Ví dụ 1: Xử lý thông tin sinh viên

python
# xu_ly_thong_tin_sinh_vien.py
print("👨‍🎓 XỬ LÝ THÔNG TIN SINH VIÊN")
print("=" * 40)

# Nhập thông tin
ho_ten_day_du = input("📝 Nhập họ tên đầy đủ: ")
email = input("📧 Nhập email: ")
so_dien_thoai = input("📱 Nhập số điện thoại: ")

# Xử lý họ tên
ho_ten_chuan = ho_ten_day_du.strip().title()
cac_tu = ho_ten_chuan.split()

if len(cac_tu) >= 2:
    ho = cac_tu[0]
    ten = cac_tu[-1]
    ten_dem = ' '.join(cac_tu[1:-1]) if len(cac_tu) > 2 else ""
else:
    ho = ho_ten_chuan
    ten = ""
    ten_dem = ""

# Xử lý email
email_sach = email.strip().lower()
ten_miền = email_sach.split('@')[-1] if '@' in email_sach else ""

# Xử lý số điện thoại
sdt_sach = ''.join(filter(str.isdigit, so_dien_thoai))

# Tạo mã sinh viên từ tên
ma_sv = ""
for tu in cac_tu:
    if tu:
        ma_sv += tu[0].upper()
ma_sv += sdt_sach[-4:] if len(sdt_sach) >= 4 else "0000"

# Hiển thị kết quả
print(f"\n📋 THÔNG TIN ĐÃ XỬ LÝ:")
print("-" * 30)
print(f"👤 Họ: {ho}")
print(f"👤 Tên đệm: {ten_dem}")
print(f"👤 Tên: {ten}")
print(f"📧 Email: {email_sach}")
print(f"🏢 Tên miền: {ten_miền}")
print(f"📱 SĐT: {sdt_sach}")
print(f"🆔 Mã SV: {ma_sv}")

# Kiểm tra tính hợp lệ
print(f"\n✅ KIỂM TRA:")
print(f"Email hợp lệ: {'@' in email_sach and '.' in ten_miền}")
print(f"SĐT hợp lệ: {len(sdt_sach) >= 10}")
print(f"Họ tên hợp lệ: {len(ho_ten_chuan.split()) >= 2}")

Ví dụ 2: Trình soạn thảo văn bản mini

python
# trinh_soan_thao_mini.py
print("📝 TRÌNH SOẠN THẢO VĂN BẢN MINI")
print("=" * 40)

def phan_tich_van_ban(text):
    """Phân tích thống kê văn bản"""
    # Thống kê cơ bản
    so_ky_tu = len(text)
    so_ky_tu_khong_khoang_trang = len(text.replace(' ', ''))
    so_tu = len(text.split())
    so_dong = text.count('\n') + 1 if text else 0
    
    # Tìm từ dài nhất
    cac_tu = text.split()
    tu_dai_nhat = max(cac_tu, key=len) if cac_tu else ""
    
    # Đếm nguyên âm
    nguyen_am = "aeiouáàảãạăắằẳẵặâấầẩẫậéèẻẽẹêếềểễệíìỉĩịóòỏõọôốồổỗộơớờởỡợúùủũụưứừửữựýỳỷỹỵ"
    so_nguyen_am = sum(1 for char in text.lower() if char in nguyen_am)
    
    return {
        'so_ky_tu': so_ky_tu,
        'so_ky_tu_khong_khoang_trang': so_ky_tu_khong_khoang_trang,
        'so_tu': so_tu,
        'so_dong': so_dong,
        'tu_dai_nhat': tu_dai_nhat,
        'so_nguyen_am': so_nguyen_am
    }

def hien_thi_menu():
    """Hiển thị menu tùy chọn"""
    print("\n🛠️ MENU:")
    print("1. ➕ Nhập văn bản")
    print("2. 📊 Phân tích văn bản")
    print("3. 🔍 Tìm và thay thế")
    print("4. 🔠 Chuyển đổi case")
    print("5. 📄 Hiển thị văn bản")
    print("0. 🚪 Thoát")

van_ban = ""

while True:
    hien_thi_menu()
    lua_chon = input("\n👉 Chọn chức năng: ")
    
    if lua_chon == "1":
        print("\n📝 Nhập văn bản (nhập 'END' trên dòng mới để kết thúc):")
        lines = []
        while True:
            line = input()
            if line == "END":
                break
            lines.append(line)
        van_ban = '\n'.join(lines)
        print("✅ Đã lưu văn bản!")
        
    elif lua_chon == "2":
        if not van_ban:
            print("❌ Chưa có văn bản để phân tích!")
            continue
            
        stats = phan_tich_van_ban(van_ban)
        print(f"\n📊 THỐNG KÊ VĂN BẢN:")
        print("-" * 25)
        print(f"📏 Số ký tự: {stats['so_ky_tu']:,}")
        print(f"🔤 Ký tự (không khoảng trắng): {stats['so_ky_tu_khong_khoang_trang']:,}")
        print(f"📝 Số từ: {stats['so_tu']:,}")
        print(f"📄 Số dòng: {stats['so_dong']:,}")
        print(f"📏 Từ dài nhất: '{stats['tu_dai_nhat']}'")
        print(f"🔤 Số nguyên âm: {stats['so_nguyen_am']:,}")
        
        if stats['so_tu'] > 0:
            tb_ky_tu_moi_tu = stats['so_ky_tu_khong_khoang_trang'] / stats['so_tu']
            print(f"📊 TB ký tự/từ: {tb_ky_tu_moi_tu:.1f}")
            
    elif lua_chon == "3":
        if not van_ban:
            print("❌ Chưa có văn bản!")
            continue
            
        tu_tim = input("🔍 Nhập từ cần tìm: ")
        tu_thay = input("🔄 Nhập từ thay thế: ")
        
        so_lan = van_ban.count(tu_tim)
        if so_lan > 0:
            van_ban = van_ban.replace(tu_tim, tu_thay)
            print(f"✅ Đã thay thế {so_lan} lần!")
        else:
            print("❌ Không tìm thấy từ cần thay thế!")
            
    elif lua_chon == "4":
        if not van_ban:
            print("❌ Chưa có văn bản!")
            continue
            
        print("\n🔠 Chọn kiểu chuyển đổi:")
        print("1. VIẾT HOA")
        print("2. viết thường") 
        print("3. Viết Hoa Đầu Từ")
        print("4. Viết hoa đầu câu")
        
        kieu = input("Chọn: ")
        if kieu == "1":
            van_ban = van_ban.upper()
        elif kieu == "2":
            van_ban = van_ban.lower()
        elif kieu == "3":
            van_ban = van_ban.title()
        elif kieu == "4":
            van_ban = van_ban.capitalize()
        else:
            print("❌ Lựa chọn không hợp lệ!")
            continue
        print("✅ Đã chuyển đổi!")
        
    elif lua_chon == "5":
        if not van_ban:
            print("❌ Chưa có văn bản!")
        else:
            print(f"\n📄 VĂN BẢN HIỆN TẠI:")
            print("-" * 30)
            print(van_ban)
            print("-" * 30)
            
    elif lua_chon == "0":
        print("👋 Tạm biệt!")
        break
    else:
        print("❌ Lựa chọn không hợp lệ!")

Ví dụ 3: Validator dữ liệu

python
# validator_du_lieu.py
import re

def kiem_tra_email(email):
    """Kiểm tra tính hợp lệ của email"""
    pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
    return re.match(pattern, email) is not None

def kiem_tra_so_dien_thoai(sdt):
    """Kiểm tra số điện thoại Việt Nam"""
    # Loại bỏ khoảng trắng và ký tự đặc biệt
    sdt_sach = re.sub(r'[^\d+]', '', sdt)
    
    # Pattern cho số VN
    patterns = [
        r'^(\+84|84|0)(3|5|7|8|9)\d{8}$',  # Mobile
        r'^(\+84|84|0)(2[0-9])\d{8}$'      # Landline
    ]
    
    return any(re.match(pattern, sdt_sach) for pattern in patterns)

def kiem_tra_mat_khau(password):
    """Kiểm tra độ mạnh mật khẩu"""
    if len(password) < 8:
        return False, "Mật khẩu phải có ít nhất 8 ký tự"
    
    if not re.search(r'[A-Z]', password):
        return False, "Mật khẩu phải có ít nhất 1 chữ hoa"
    
    if not re.search(r'[a-z]', password):
        return False, "Mật khẩu phải có ít nhất 1 chữ thường"
    
    if not re.search(r'\d', password):
        return False, "Mật khẩu phải có ít nhất 1 số"
    
    if not re.search(r'[!@#$%^&*(),.?":{}|<>]', password):
        return False, "Mật khẩu phải có ít nhất 1 ký tự đặc biệt"
    
    return True, "Mật khẩu mạnh"

def format_ten_nguoi(ten):
    """Chuẩn hóa tên người"""
    # Loại bỏ khoảng trắng thừa
    ten = ' '.join(ten.split())
    
    # Viết hoa chữ cái đầu mỗi từ
    ten = ten.title()
    
    # Xử lý các trường hợp đặc biệt
    replacements = {
        ' Van ': ' Văn ',
        ' Thi ': ' Thị ',
        ' Duc ': ' Đức ',
        ' Anh ': ' Anh ',
    }
    
    for old, new in replacements.items():
        ten = ten.replace(old, new)
    
    return ten

# Test validator
print("🔍 VALIDATOR DỮ LIỆU")
print("=" * 30)

while True:
    print("\n📝 Chọn loại kiểm tra:")
    print("1. 📧 Email")
    print("2. 📱 Số điện thoại")
    print("3. 🔒 Mật khẩu")
    print("4. 👤 Tên người")
    print("0. 🚪 Thoát")
    
    lua_chon = input("\nChọn: ")
    
    if lua_chon == "1":
        email = input("Nhập email: ")
        if kiem_tra_email(email):
            print("✅ Email hợp lệ!")
        else:
            print("❌ Email không hợp lệ!")
            
    elif lua_chon == "2":
        sdt = input("Nhập số điện thoại: ")
        if kiem_tra_so_dien_thoai(sdt):
            print("✅ Số điện thoại hợp lệ!")
        else:
            print("❌ Số điện thoại không hợp lệ!")
            
    elif lua_chon == "3":
        password = input("Nhập mật khẩu: ")
        hop_le, thong_bao = kiem_tra_mat_khau(password)
        if hop_le:
            print(f"✅ {thong_bao}")
        else:
            print(f"❌ {thong_bao}")
            
    elif lua_chon == "4":
        ten = input("Nhập tên: ")
        ten_chuan = format_ten_nguoi(ten)
        print(f"📝 Tên chuẩn: {ten_chuan}")
        
    elif lua_chon == "0":
        print("👋 Tạm biệt!")
        break
    else:
        print("❌ Lựa chọn không hợp lệ!")

🏋️ Thực hành

Bài tập 1: Phân tích URL

Nhiệm vụ: Tách các thành phần của URL

python
# TODO: Nhập URL và tách thành:
# - Protocol (http, https)
# - Domain
# - Path
# - Query parameters

Đáp án:

python
# phan_tich_url.py
def phan_tich_url(url):
    """Phân tích URL thành các thành phần"""
    # Tách protocol
    if '://' in url:
        protocol, phan_con = url.split('://', 1)
    else:
        protocol = 'unknown'
        phan_con = url
    
    # Tách query string
    if '?' in phan_con:
        phan_con, query = phan_con.split('?', 1)
    else:
        query = ''
    
    # Tách domain và path
    if '/' in phan_con:
        domain, path = phan_con.split('/', 1)
        path = '/' + path
    else:
        domain = phan_con
        path = '/'
    
    return {
        'protocol': protocol,
        'domain': domain,
        'path': path,
        'query': query,
        'full_url': url
    }

# Test
url = input("Nhập URL: ")
result = phan_tich_url(url)

print("\n📊 PHÂN TÍCH URL:")
for key, value in result.items():
    print(f"{key}: {value}")

Bài tập 2: Mã hóa Caesar

Nhiệm vụ: Implement thuật toán mã hóa Caesar

python
# TODO: Mã hóa và giải mã Caesar cipher
# - Dịch chuyển ký tự theo một số bước
# - Xử lý cả chữ hoa và chữ thường
# - Giữ nguyên ký tự đặc biệt

Đáp án:

python
# caesar_cipher.py
def ma_hoa_caesar(text, shift):
    """Mã hóa Caesar với số bước dịch chuyển"""
    result = ""
    
    for char in text:
        if char.isalpha():
            # Xác định base (A hoặc a)
            base = ord('A') if char.isupper() else ord('a')
            # Dịch chuyển và wrap around
            shifted = (ord(char) - base + shift) % 26
            result += chr(base + shifted)
        else:
            # Giữ nguyên ký tự không phải chữ cái
            result += char
    
    return result

def giai_ma_caesar(text, shift):
    """Giải mã Caesar"""
    return ma_hoa_caesar(text, -shift)

# Test
text = input("Nhập văn bản: ")
shift = int(input("Nhập số bước dịch: "))

ma_hoa = ma_hoa_caesar(text, shift)
giai_ma = giai_ma_caesar(ma_hoa, shift)

print(f"Văn bản gốc: {text}")
print(f"Mã hóa: {ma_hoa}")
print(f"Giải mã: {giai_ma}")

Bài tập 3: Text formatter

Nhiệm vụ: Tool định dạng văn bản đa chức năng

python
# TODO: Tạo tool format văn bản:
# - Căn lề (trái, phải, giữa)
# - Wrap text theo độ rộng
# - Thêm border
# - Số hóa dòng

Đáp án:

python
# text_formatter.py
def can_trai(text, width):
    """Căn trái văn bản"""
    lines = text.split('\n')
    return '\n'.join(line.ljust(width) for line in lines)

def can_phai(text, width):
    """Căn phải văn bản"""  
    lines = text.split('\n')
    return '\n'.join(line.rjust(width) for line in lines)

def can_giua(text, width):
    """Căn giữa văn bản"""
    lines = text.split('\n')
    return '\n'.join(line.center(width) for line in lines)

def them_border(text, char='*'):
    """Thêm border xung quanh văn bản"""
    lines = text.split('\n')
    max_length = max(len(line) for line in lines)
    
    border_line = char * (max_length + 4)
    result = [border_line]
    
    for line in lines:
        result.append(f"{char} {line.ljust(max_length)} {char}")
    
    result.append(border_line)
    return '\n'.join(result)

def so_hoa_dong(text):
    """Thêm số dòng"""
    lines = text.split('\n')
    max_digits = len(str(len(lines)))
    
    result = []
    for i, line in enumerate(lines, 1):
        line_num = str(i).rjust(max_digits)
        result.append(f"{line_num}| {line}")
    
    return '\n'.join(result)

# Menu chính
text = input("Nhập văn bản cần format: ")

while True:
    print("\n🎨 TEXT FORMATTER")
    print("1. Căn trái")
    print("2. Căn phải")  
    print("3. Căn giữa")
    print("4. Thêm border")
    print("5. Số hóa dòng")
    print("6. Hiển thị văn bản")
    print("0. Thoát")
    
    choice = input("Chọn: ")
    
    if choice == "1":
        width = int(input("Độ rộng: "))
        text = can_trai(text, width)
        print("✅ Đã căn trái!")
    elif choice == "2":
        width = int(input("Độ rộng: "))
        text = can_phai(text, width)
        print("✅ Đã căn phải!")
    elif choice == "3":
        width = int(input("Độ rộng: "))
        text = can_giua(text, width)
        print("✅ Đã căn giữa!")
    elif choice == "4":
        char = input("Ký tự border (mặc định *): ") or "*"
        text = them_border(text, char)
        print("✅ Đã thêm border!")
    elif choice == "5":
        text = so_hoa_dong(text)
        print("✅ Đã số hóa dòng!")
    elif choice == "6":
        print("\n📄 VĂN BẢN:")
        print("-" * 30)
        print(text)
        print("-" * 30)
    elif choice == "0":
        break
    else:
        print("❌ Lựa chọn không hợp lệ!")

📋 Tóm tắt

Cách tạo chuỗi:

CáchCú phápSử dụng khi
Nháy đơn'text'Chuỗi đơn giản
Nháy đôi"text"Có nháy đơn bên trong
Triple quotes"""text"""Nhiều dòng
Raw stringr'text'Đường dẫn, regex

Thao tác chuỗi quan trọng:

python
# Truy cập
text[0]         # Ký tự đầu
text[-1]        # Ký tự cuối
text[1:5]       # Cắt từ vị trí 1 đến 4

# Tìm kiếm
'sub' in text   # Kiểm tra có chứa
text.find('sub') # Vị trí đầu tiên
text.count('x') # Đếm số lần xuất hiện

# Thay đổi
text.upper()    # Viết hoa
text.lower()    # Viết thường
text.strip()    # Xóa khoảng trắng
text.replace('old', 'new')  # Thay thế

Định dạng chuỗi:

python
# F-string (khuyến nghị)
f"Hello {name}, you are {age} years old"

# .format()
"Hello {}, you are {} years old".format(name, age)

# % formatting (cũ)
"Hello %s, you are %d years old" % (name, age)

Patterns thường dùng:

python
# Kiểm tra và xử lý input
user_input = input("Nhập: ").strip().lower()

# Tách và xử lý
parts = data.split(',')
cleaned = [part.strip() for part in parts]

# Tạo slug từ tiêu đề
slug = title.lower().replace(' ', '-')

# Kiểm tra định dạng
if text.startswith('http'):
    # Xử lý URL

Best practices:

  1. 🎯 Sử dụng f-string cho định dạng
  2. 🧹 Luôn .strip() input từ người dùng
  3. 🔍 Dùng .lower() khi so sánh không phân biệt hoa thường
  4. 📝 Raw string cho regex và đường dẫn
  5. ✂️ Slicing thay vì vòng lặp khi có thể

Chuẩn bị cho bài tiếp theo:

Bài tiếp theo sẽ học về ✅ Kiểu logic (bool) - cách làm việc với True/False và logic trong Python!


💡 Mẹo: Chuỗi trong Python là immutable (không thay đổi được). Mọi thao tác đều tạo ra chuỗi mới!

🔤 Thực hành: Thử tạo một chương trình xử lý tên file để hiểu rõ sức mạnh của string methods!

🐍 Khóa học Python căn bản bằng tiếng Việt