Bài 4: Strings - Chuỗi Ký Tự

Mục Tiêu Bài Học

Sau khi hoàn thành bài này, bạn sẽ:

  • ✅ Hiểu string là gì và cách tạo strings
  • ✅ Sử dụng string indexing và slicing
  • ✅ Áp dụng string methods phổ biến
  • ✅ Format strings với f-strings
  • ✅ Xử lý strings trong thực tế

String Là Gì?

String (chuỗi) là kiểu dữ liệu dùng để lưu trữ text (văn bản). String là một sequence (chuỗi) các ký tự.

# Stringsname = "Python"message = 'Hello World'empty = "" print(type(name))  # <class 'str'>

Tạo Strings

Single vs Double Quotes:

# Cả hai đều tạo string giống nhaustr1 = "Hello"str2 = 'Hello'print(str1 == str2)  # True # Chọn quote để tránh escapemessage1 = "He said 'Hello'"      # ✅ Dễ đọcmessage2 = 'He said "Hello"'      # ✅ Dễ đọcmessage3 = "He said \"Hello\""    # ❌ Khó đọc hơn

Triple Quotes (Multi-line):

# Chuỗi nhiều dòngpoem = """Roses are red,Violets are blue,Python is awesome,And so are you!"""print(poem) # Có thể dùng ''' thay """text = '''Dòng 1Dòng 2Dòng 3'''

Raw Strings:

# String thông thường: \n là newlinepath1 = "C:\new\folder"print(path1)  # C:              # ew\folder (lỗi!) # Raw string: \n là ký tự \ và npath2 = r"C:\new\folder"print(path2)  # C:\new\folder ✅ # Hữu ích cho regexpattern = r"\d{3}-\d{4}"  # Regex pattern

String Indexing - Truy Cập Ký Tự

Mỗi ký tự trong string có một index (chỉ số).

text = "Python"#       012345   (positive index)#      -654321   (negative index) # Positive indexing (từ trái sang phải, bắt đầu từ 0)print(text[0])   # P (ký tự đầu)print(text[1])   # yprint(text[5])   # n (ký tự cuối) # Negative indexing (từ phải sang trái, bắt đầu từ -1)print(text[-1])  # n (ký tự cuối)print(text[-2])  # oprint(text[-6])  # P (ký tự đầu)

Lỗi Index Out of Range:

text = "Hello"# print(text[10])  # IndexError!# print(text[-10]) # IndexError! # Check length trướcif len(text) > 10:    print(text[10])else:    print("Index quá lớn")

Ứng dụng:

# Lấy chữ cái đầuname = "Nguyen Van An"initials = name[0] + name[7] + name[11]print(initials)  # NVA # Lấy ký tự cuốifilename = "document.pdf"extension = filename[-3:]  # pdf

String Slicing - Cắt Chuỗi

Lấy một phần của string.

Cú Pháp Cơ Bản

# Syntax: string[start:stop:step]text = "Python Programming"#       0123456789... # [start:stop] - từ start đến stop-1print(text[0:6])    # Pythonprint(text[7:18])   # Programming # Bỏ start - từ đầuprint(text[:6])     # Python # Bỏ stop - đến cuốiprint(text[7:])     # Programming # Bỏ cả hai - toàn bộprint(text[:])      # Python Programming

Negative Slicing

text = "Hello World" # Negative indicesprint(text[-5:])     # Worldprint(text[:-6])     # Helloprint(text[-11:-6])  # Hello

Step (Bước Nhảy)

text = "Python Programming" # Step = 2 (lấy mỗi 2 ký tự)print(text[::2])     # Pto rgamn # Step = 3print(text[::3])     # Ph ormn # Đảo ngược string (step = -1)print(text[::-1])    # gnimmargorP nohtyP # Đảo ngược từng từprint(text[6::-1])   # nohtyP

Ví dụ thực tế:

# Lấy domain từ emailemail = "[email protected]"at_index = email.index('@')domain = email[at_index+1:]print(domain)  # example.com # Lấy tên filefilepath = "/home/user/document.txt"filename = filepath[filepath.rfind('/')+1:]print(filename)  # document.txt # Ẩn số thẻcard_number = "1234567890123456"hidden = "*" * 12 + card_number[-4:]print(hidden)  # ************3456 # Kiểm tra palindromeword = "madam"is_palindrome = word == word[::-1]print(f"{word} is palindrome: {is_palindrome}")  # True

String Concatenation - Nối Chuỗi

Dùng Toán Tử +

first = "Hello"second = "World"result = first + " " + secondprint(result)  # Hello World # Nối nhiều stringsgreeting = "Hello" + " " + "Python" + " " + "World"print(greeting) # Lỗi: không thể nối string với numberage = 25# message = "Age: " + age  # TypeError!message = "Age: " + str(age)  # ✅ Convert sang stringprint(message)

Dùng Toán Tử *

# Lặp lại stringseparator = "-" * 40print(separator)  # ---------------------------------------- # Tạo patternpattern = "AB" * 5print(pattern)  # ABABABABAB # Khoảng trắngspaces = " " * 10centered = spaces + "Title" + spaces

Dùng join()

# Nối list thành stringwords = ["Python", "is", "awesome"]sentence = " ".join(words)print(sentence)  # Python is awesome # Nối với separator khácitems = ["apple", "banana", "orange"]result = ", ".join(items)print(result)  # apple, banana, orange # Nối lineslines = ["Line 1", "Line 2", "Line 3"]text = "\n".join(lines)print(text)

String Methods - Phương Thức Chuỗi

Case Conversion - Chuyển Đổi Chữ Hoa/Thường

text = "Python Programming" # upper() - Chữ HOA toàn bộprint(text.upper())        # PYTHON PROGRAMMING # lower() - Chữ thường toàn bộprint(text.lower())        # python programming # capitalize() - Viết hoa chữ đầutext2 = "hello world"print(text2.capitalize())  # Hello world # title() - Viết hoa đầu mỗi từprint(text2.title())       # Hello World # swapcase() - Đảo chữ hoa/thườngtext3 = "Hello World"print(text3.swapcase())    # hELLO wORLD

Ứng dụng:

# So sánh không phân biệt hoa/thườngusername = "ADMIN"if username.lower() == "admin":    print("Welcome, admin!") # Chuẩn hóa inputname = input("Your name: ")name = name.strip().title()  # Xóa khoảng trắng, viết hoaprint(f"Hello, {name}!")

Strip Methods - Xóa Khoảng Trắng

text = "   Hello World   " # strip() - Xóa khoảng trắng 2 đầuprint(text.strip())        # "Hello World" # lstrip() - Xóa bên tráiprint(text.lstrip())       # "Hello World   " # rstrip() - Xóa bên phảiprint(text.rstrip())       # "   Hello World" # Xóa ký tự kháctext2 = "***Python***"print(text2.strip('*'))    # Python # Xóa nhiều ký tựtext3 = "...Hello..."print(text3.strip('.'))    # Hello

Search Methods - Tìm Kiếm

text = "Python Programming is fun" # find() - Tìm vị trí đầu tiên (trả về -1 nếu không tìm thấy)print(text.find("Programming"))  # 7print(text.find("Java"))         # -1 # index() - Giống find() nhưng raise ValueError nếu không tìm thấyprint(text.index("Python"))      # 0# print(text.index("Java"))      # ValueError! # rfind() - Tìm từ phải sang tráitext2 = "hello hello hello"print(text2.find("hello"))       # 0 (đầu tiên)print(text2.rfind("hello"))      # 12 (cuối cùng) # count() - Đếm số lần xuất hiệnprint(text2.count("hello"))      # 3

Check Methods - Kiểm Tra

# startswith() - Kiểm tra bắt đầuemail = "[email protected]"print(email.startswith("user"))    # Trueprint(email.startswith("admin"))   # False # endswith() - Kiểm tra kết thúcfilename = "document.pdf"print(filename.endswith(".pdf"))   # Trueprint(filename.endswith(".txt"))   # False # in operator - Kiểm tra chứatext = "Python is awesome"print("Python" in text)            # Trueprint("Java" in text)              # Falseprint("Python" not in text)        # False

Ứng dụng:

# Validate emailemail = input("Email: ")if "@" in email and email.endswith(".com"):    print("Email hợp lệ")else:    print("Email không hợp lệ") # Check file extensionfilename = "data.csv"if filename.endswith(('.csv', '.txt', '.json')):    print("File format supported")

Character Type Check

# isalpha() - Chỉ chứa chữ cáiprint("abc".isalpha())       # Trueprint("abc123".isalpha())    # False # isdigit() - Chỉ chứa sốprint("123".isdigit())       # Trueprint("12.3".isdigit())      # False # isalnum() - Chữ cái hoặc sốprint("abc123".isalnum())    # Trueprint("abc 123".isalnum())   # False (có space) # isspace() - Chỉ chứa khoảng trắngprint("   ".isspace())       # Trueprint(" a ".isspace())       # False # isupper() - Chữ HOAprint("PYTHON".isupper())    # Trueprint("Python".isupper())    # False # islower() - Chữ thườngprint("python".islower())    # Trueprint("Python".islower())    # False

Ứng dụng:

# Validate username (chỉ chữ và số)username = input("Username: ")if username.isalnum() and len(username) >= 3:    print("Username hợp lệ")else:    print("Username phải có ít nhất 3 ký tự chữ/số") # Validate số điện thoạiphone = input("Phone: ")phone = phone.replace(" ", "").replace("-", "")if phone.isdigit() and len(phone) == 10:    print("Số điện thoại hợp lệ")

Replace và Split

# replace() - Thay thếtext = "Hello World"new_text = text.replace("World", "Python")print(new_text)  # Hello Python # Replace all occurrencestext2 = "one two one three one"new_text2 = text2.replace("one", "1")print(new_text2)  # 1 two 1 three 1 # Replace với limittext3 = "one one one one"new_text3 = text3.replace("one", "1", 2)  # Chỉ thay 2 cái đầuprint(new_text3)  # 1 1 one one # split() - Tách thành listsentence = "Python is awesome"words = sentence.split()  # Tách theo spaceprint(words)  # ['Python', 'is', 'awesome'] # Split với delimitercsv = "John,25,USA"data = csv.split(",")print(data)  # ['John', '25', 'USA'] # Split với limittext4 = "a-b-c-d-e"parts = text4.split("-", 2)  # Chỉ split 2 lầnprint(parts)  # ['a', 'b', 'c-d-e']

Ứng dụng:

# Parse CSVline = "John,Doe,30,USA"fields = line.split(",")first_name, last_name, age, country = fieldsprint(f"Name: {first_name} {last_name}")print(f"Age: {age}")print(f"Country: {country}") # Clean texttext = "Hello    World"clean = " ".join(text.split())  # Remove extra spacesprint(clean)  # Hello World # URL slugtitle = "Python Programming Tutorial"slug = title.lower().replace(" ", "-")print(slug)  # python-programming-tutorial

String Formatting

1. Old Style (%) - Không khuyến nghị

name = "An"age = 25print("Name: %s, Age: %d" % (name, age))# Name: An, Age: 25

2. format() Method

name = "An"age = 25 # Positional argumentsprint("Name: {}, Age: {}".format(name, age)) # Named argumentsprint("Name: {n}, Age: {a}".format(n=name, a=age)) # Indexprint("Name: {0}, Age: {1}, Name again: {0}".format(name, age))

3. f-strings (Python 3.6+) - Khuyến nghị ⭐

Cú pháp cơ bản:

name = "An"age = 25 # f-stringmessage = f"Name: {name}, Age: {age}"print(message)  # Name: An, Age: 25 # Expressions trong f-stringsprint(f"Next year: {age + 1}")  # Next year: 26print(f"Uppercase: {name.upper()}")  # Uppercase: AN

Number Formatting:

# Decimal placesprice = 19.99print(f"Price: {price:.2f}")  # Price: 19.99 pi = 3.14159265359print(f"Pi: {pi:.2f}")   # Pi: 3.14print(f"Pi: {pi:.4f}")   # Pi: 3.1416 # Thousands separatornumber = 1000000print(f"Number: {number:,}")  # Number: 1,000,000 # Combinationprice = 1234567.89print(f"Price: {price:,.2f} VND")  # Price: 1,234,567.89 VND # Percentagerate = 0.15print(f"Rate: {rate:.1%}")  # Rate: 15.0%

Alignment:

name = "Python" # Left alignprint(f"|{name:<10}|")  # |Python    | # Right alignprint(f"|{name:>10}|")  # |    Python| # Centerprint(f"|{name:^10}|")  # |  Python  | # Padding với ký tự khácprint(f"|{name:*<10}|")  # |Python****|print(f"|{name:*>10}|")  # |****Python|print(f"|{name:*^10}|")  # |**Python**|

Width và Precision:

# Integer widthnum = 42print(f"{num:5d}")    # "   42"print(f"{num:05d}")   # "00042" (pad với 0) # Float width và precisionvalue = 123.456print(f"{value:10.2f}")   # "    123.46"print(f"{value:010.2f}")  # "0000123.46"

Multi-line f-strings:

name = "An"age = 25city = "Hanoi" # Multi-lineprofile = f"""Name: {name}Age: {age}City: {city}"""print(profile) # Expression trên nhiều dòngresult = f"Total: {    100 + 200 + 300}"print(result)  # Total: 600

Debug với f-strings (Python 3.8+):

x = 10y = 20 # = để show cả tên biến và giá trịprint(f"{x=}")     # x=10print(f"{y=}")     # y=20print(f"{x+y=}")   # x+y=30 # Hữu ích cho debuggingresult = x * yprint(f"{result=}")  # result=200

Escape Characters

# \n - New lineprint("Line 1\nLine 2")# Line 1# Line 2 # \t - Tabprint("Name:\tJohn")# Name:   John # \\ - Backslashprint("Path: C:\\Users\\Admin")# Path: C:\Users\Admin # \' - Single quoteprint('It\'s a beautiful day')# It's a beautiful day # \" - Double quoteprint("He said \"Hello\"")# He said "Hello" # \r - Carriage returnprint("Hello\rWorld")  # World (overwrite) # \b - Backspaceprint("Hello\b\b\b123")  # He123

Ví Dụ Thực Tế

1. Text Processing

# Input texttext = """   Python is a powerful programming language.   It is easy to LEARN and USE.   Python is widely used in web development, data science, and AI.""" # Clean và formattext = text.strip()  # Xóa khoảng trắng đầu/cuốitext = text.lower()  # Chuyển thườngtext = text.replace("python", "Python")  # Capitalize tên riêng # Count wordswords = text.split()word_count = len(words) # Count specific wordpython_count = text.lower().count("python") # Displayprint(f"Text: {text}")print(f"Word count: {word_count}")print(f"'Python' appears: {python_count} times")

2. Email Validator

def validate_email(email):    """Validate email format"""    # Xóa khoảng trắng    email = email.strip().lower()        # Check có @ không    if '@' not in email:        return False, "Missing @"        # Split username và domain    parts = email.split('@')    if len(parts) != 2:        return False, "Invalid @ usage"        username, domain = parts        # Check username    if len(username) < 1:        return False, "Username too short"        # Check domain    if '.' not in domain:        return False, "Domain missing ."        # Check domain extension    if not domain.endswith(('.com', '.vn', '.net', '.org')):        return False, "Invalid domain extension"        return True, "Valid email" # Testemails = [    "[email protected]",    "invalid.email",    "@example.com",    "user@",    "user@example"] for email in emails:    valid, message = validate_email(email)    print(f"{email:<25} -> {message}")

3. Text Formatter

def format_text_box(text, width=50):    """Format text trong box"""    # Split thành dòng    words = text.split()    lines = []    current_line = []    current_length = 0        for word in words:        word_length = len(word)        # +1 cho space        if current_length + word_length + len(current_line) <= width - 4:            current_line.append(word)            current_length += word_length        else:            lines.append(" ".join(current_line))            current_line = [word]            current_length = word_length        if current_line:        lines.append(" ".join(current_line))        # Draw box    border = "+" + "-" * (width - 2) + "+"    print(border)        for line in lines:        padding = width - len(line) - 4        print(f"| {line}{' ' * padding} |")        print(border) # Testtext = """Python is an amazing programming language that is easy to learn and powerful to use in various applications."""format_text_box(text.strip())

4. Username Generator

def generate_username(full_name):    """Generate username từ họ tên"""    # Clean input    full_name = full_name.strip().lower()        # Remove extra spaces    full_name = " ".join(full_name.split())        # Split name    parts = full_name.split()        if len(parts) == 1:        # Chỉ có 1 từ        username = parts[0]    else:        # Lấy chữ cái đầu các từ trước + từ cuối        initials = "".join([p[0] for p in parts[:-1]])        last = parts[-1]        username = initials + last        # Remove special characters    username = "".join(c for c in username if c.isalnum())        return username # Testnames = [    "Nguyen Van An",    "Tran Thi Binh",    "Le Hoang Nam",    "Python"] for name in names:    username = generate_username(name)    print(f"{name:<20} -> {username}")

Bài Tập Thực Hành

Bài 1: String Reverser

Viết chương trình:

  • Input: Một câu
  • Output: Câu đảo ngược, mỗi từ cũng đảo ngược

Bài 2: Password Validator

Kiểm tra password hợp lệ:

  • Ít nhất 8 ký tự
  • Có chữ hoa
  • Có chữ thường
  • Có số
  • Có ký tự đặc biệt

Bài 3: Word Counter

Nhập đoạn văn, đếm:

  • Số từ
  • Số câu
  • Số ký tự
  • Từ dài nhất

Bài 4: Title Case Converter

Viết hoa chữ đầu mỗi từ, TRỪ:

  • a, an, the
  • and, or, but
  • in, on, at

Bài 5: Phone Number Formatter

Format số điện thoại:

  • Input: "0123456789"
  • Output: "012-345-6789" hoặc "(012) 345-6789"

Tóm Tắt

✅ String là sequence của ký tự
✅ Indexing: text[0], text[-1]
✅ Slicing: text[start:stop:step]
✅ Methods: upper(), lower(), strip(), split(), replace()
✅ Formatting: f-strings f"Value: {variable}"
✅ Escape characters: \n, \t, \\, \', \"
✅ Strings are immutable (không thể thay đổi)

Bài Tiếp Theo

Bài 5: Lists - Học về lists, list methods và list comprehensions.


Remember:

  • Strings are immutable (tạo string mới khi thay đổi)
  • f-strings là cách tốt nhất để format strings
  • Dùng methods thay vì viết logic từ đầu
  • Practice với text processing thực tế!