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ế!