MinAI - Về trang chủ
Thực hành
3/152 giờ
Đang tải...

Thực Hành Python Cơ Bản

Bài tập thực hành Variables, Data Types, Control Flow, Functions và Collections

0

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

TB5 min

Sau bài thực hành này, bạn sẽ:

✅ Thành thạo Variables, Data Types, Operators qua bài tập thực tế

✅ Viết được Control Flow và List Comprehension thành thạo

✅ Xây dựng Functions hoàn chỉnh cho các bài toán thực tế

✅ Sử dụng Collections hiệu quả trong xử lý dữ liệu

Thời gian: 2 giờ | Độ khó: Beginner → Intermediate | Yêu cầu: Hoàn thành Bài 1-2

1

🟢 Phần 1: Variables và Data Types (Easy)

TB5 min

Bài 1.1: Thông tin cá nhân

Tạo các biến lưu thông tin cá nhân, sau đó in ra card giới thiệu.

Python
1# Tạo biến
2name = "Nguyễn Văn A"
3age = 22
4gpa = 3.75
5is_graduated = False
6major = "Data Science"
7
8# In card giới thiệu
9print("=" * 40)
10print(f"{'THÔNG TIN SINH VIÊN':^40}")
11print("=" * 40)
12print(f"Họ tên: {name}")
13print(f"Tuổi: {age}")
14print(f"GPA: {gpa:.2f}")
15print(f"Ngành: {major}")
16print(f"Tốt nghiệp: {'Rồi' if is_graduated else 'Chưa'}")
17print("=" * 40)

Bài 1.2: Chuyển đổi nhiệt độ

Đề bài: Viết code chuyển đổi Celsius ↔ Fahrenheit
Python
1# Công thức: F = C × 9/5 + 32
2def celsius_to_fahrenheit(c):
3 return c * 9/5 + 32
4
5def fahrenheit_to_celsius(f):
6 return (f - 32) * 5/9
7
8# Test
9temps_c = [0, 25, 37, 100]
10for c in temps_c:
11 f = celsius_to_fahrenheit(c)
12 print(f"{c}°C = {f:.1f}°F")
13
14# Output:
15# 0°C = 32.0°F
16# 25°C = 77.0°F
17# 37°C = 98.6°F
18# 100°C = 212.0°F

Bài 1.3: Tính BMI

Đề bài: Nhập cân nặng (kg) và chiều cao (m), tính BMI và phân loại
Python
1def calculate_bmi(weight, height):
2 bmi = weight / (height ** 2)
3
4 if bmi < 18.5:
5 category = "Gầy"
6 elif bmi < 25:
7 category = "Bình thường"
8 elif bmi < 30:
9 category = "Thừa cân"
10 else:
11 category = "Béo phì"
12
13 return bmi, category
14
15# Test
16weight, height = 70, 1.75
17bmi, cat = calculate_bmi(weight, height)
18print(f"BMI: {bmi:.1f} → {cat}")
19# BMI: 22.9 → Bình thường

Checkpoint

Bạn đã hoàn thành 3 bài tập Easy chưa? Hãy chắc chắn bạn hiểu f-string, type conversion và ternary operator trước khi tiếp!

2

🟡 Phần 2: Control Flow và Loops (Medium)

TB5 min

Bài 2.1: FizzBuzz

Đề bài: In các số từ 1-30. Nếu chia hết cho 3 in "Fizz", chia hết cho 5 in "Buzz", cả hai in "FizzBuzz"

💡 Gợi ý
  1. Dùng vòng lặp for i in range(1, 31)
  2. Kiểm tra i % 15 == 0 TRƯỚC (vì chia hết cho cả 3 và 5)
  3. Sau đó kiểm tra i % 3 == 0, rồi i % 5 == 0
  4. Thử viết bằng list comprehension sau khi làm được cách thường!
Giải pháp
Python
1for i in range(1, 31):
2 if i % 15 == 0:
3 print("FizzBuzz")
4 elif i % 3 == 0:
5 print("Fizz")
6 elif i % 5 == 0:
7 print("Buzz")
8 else:
9 print(i)
10
11# List comprehension version
12result = ["FizzBuzz" if i%15==0 else "Fizz" if i%3==0
13 else "Buzz" if i%5==0 else str(i) for i in range(1, 31)]

Bài 2.2: Số nguyên tố

Đề bài: Tìm tất cả số nguyên tố trong khoảng 1-100

💡 Gợi ý
  1. Viết function is_prime(n) trả về True/False
  2. Số nguyên tố: chỉ chia hết cho 1 và chính nó
  3. Chỉ cần kiểm tra từ 2 đến √n (tối ưu!)
  4. Dùng list comprehension: [n for n in range(2, 101) if is_prime(n)]
Giải pháp
Python
1def is_prime(n):
2 if n < 2:
3 return False
4 for i in range(2, int(n**0.5) + 1):
5 if n % i == 0:
6 return False
7 return True
8
9primes = [n for n in range(2, 101) if is_prime(n)]
10print(f"Có {len(primes)} số nguyên tố: {primes}")
11# Có 25 số nguyên tố: [2, 3, 5, 7, 11, 13, ...]

Bài 2.3: Password Validator

Đề bài: Kiểm tra mật khẩu mạnh (≥8 ký tự, có chữ hoa, chữ thường, số, ký tự đặc biệt)

💡 Gợi ý
  1. Tạo list errors = [] để chứa lỗi
  2. Kiểm tra len(password) >= 8
  3. Dùng any(): any(c.isupper() for c in password) cho chữ hoa
  4. Tương tự cho .islower(), .isdigit(), not c.isalnum() (ký tự đặc biệt)
  5. Trả về (True, []) nếu OK, (False, errors) nếu có lỗi
Giải pháp
Python
1def validate_password(password):
2 errors = []
3
4 if len(password) < 8:
5 errors.append("Cần ít nhất 8 ký tự")
6 if not any(c.isupper() for c in password):
7 errors.append("Cần ít nhất 1 chữ hoa")
8 if not any(c.islower() for c in password):
9 errors.append("Cần ít nhất 1 chữ thường")
10 if not any(c.isdigit() for c in password):
11 errors.append("Cần ít nhất 1 chữ số")
12 if not any(c in "!@#$%^&*" for c in password):
13 errors.append("Cần ít nhất 1 ký tự đặc biệt (!@#$%^&*)")
14
15 if errors:
16 return False, errors
17 return True, ["Mật khẩu hợp lệ! ✅"]
18
19# Test
20passwords = ["abc", "Hello123", "Str0ng@Pass"]
21for pw in passwords:
22 valid, messages = validate_password(pw)
23 print(f"\n'{pw}': {'✅' if valid else '❌'}")
24 for msg in messages:
25 print(f" - {msg}")

Bài 2.4: Pattern Printing

💡 Gợi ý
  1. Tam giác: Mỗi dòng i cần (n-i) khoảng trắng + (2*i-1) dấu sao
  2. Kim cương: Nửa trên = tam giác, nửa dưới = tam giác ngược (range(n-1, 0, -1))
  3. Công thức: " " * spaces + "*" * stars
  4. Debug: In từng dòng với i để hiểu pattern
Đề bài: In tam giác sao và kim cương
Python
1# Tam giác
2n = 5
3for i in range(1, n + 1):
4 print(" " * (n - i) + "*" * (2*i - 1))
5# *
6# ***
7# *****
8# *******
9# *********
10
11# Kim cương
12for i in range(1, n + 1):
13 print(" " * (n - i) + "*" * (2*i - 1))
14for i in range(n - 1, 0, -1):
15 print(" " * (n - i) + "*" * (2*i - 1))

Checkpoint

FizzBuzz là câu hỏi phỏng vấn kinh điển. Bạn đã giải được bằng cả for loop và list comprehension chưa?

3

🟡 Phần 3: Collections (Medium)

TB5 min

Bài 3.1: Word Counter

💡 Gợi ý
  1. Dùng .lower() chuẩn hóa + .split() tách từ
  2. Tạo dict rỗng, duyệt và dict.get(word, 0) + 1
  3. Sắp xếp: sorted(dict.items(), key=lambda x: x[1], reverse=True)
  4. Hoặc dùng collections.Counter (nhanh hơn!)
Đề bài: Đếm tần suất từ trong câu, sắp xếp từ phổ biến nhất
Python
1def word_counter(text):
2 words = text.lower().split()
3 count = {}
4 for word in words:
5 word = word.strip(".,!?") # Bỏ dấu câu
6 count[word] = count.get(word, 0) + 1
7
8 # Sắp xếp theo tần suất giảm dần
9 sorted_words = sorted(count.items(), key=lambda x: x[1], reverse=True)
10 return sorted_words
11
12text = "the cat sat on the mat the cat likes the mat"
13result = word_counter(text)
14for word, freq in result:
15 print(f" '{word}': {freq} lần")
16# 'the': 4 lần, 'cat': 2 lần, 'mat': 2 lần, ...

Bài 3.2: Student Grade Manager

💡 Gợi ý
  1. Dùng closure — function trong function
  2. students = {} là biến shared giữa các inner functions
  3. Return dict các functions: {"add": add_student, "avg": get_average, ...}
  4. Rank: sorted(students.items(), key=lambda x: sum(x[1])/len(x[1]), reverse=True)
Đề bài: Quản lý điểm sinh viên — thêm, xem, tính trung bình, xếp hạng
Python
1def create_grade_manager():
2 students = {}
3
4 def add_student(name, scores):
5 students[name] = scores
6
7 def get_average(name):
8 if name not in students:
9 return None
10 scores = students[name]
11 return sum(scores) / len(scores)
12
13 def get_ranking():
14 averages = {name: sum(s)/len(s) for name, s in students.items()}
15 return sorted(averages.items(), key=lambda x: x[1], reverse=True)
16
17 def summary():
18 ranking = get_ranking()
19 print(f"\n{'Xếp hạng':^40}")
20 print("-" * 40)
21 for rank, (name, avg) in enumerate(ranking, 1):
22 grade = "A" if avg >= 9 else "B" if avg >= 8 else "C" if avg >= 7 else "D"
23 print(f" #{rank} {name:<15} TB: {avg:.1f} ({grade})")
24
25 return add_student, get_average, get_ranking, summary
26
27# Sử dụng
28add, avg, rank, summary = create_grade_manager()
29add("Alice", [9, 8.5, 9.5, 10])
30add("Bob", [7, 8, 7.5, 8])
31add("Charlie", [10, 9, 9.5, 9])
32summary()

Bài 3.3: Set Operations — Phân tích khách hàng

💡 Gợi ý
  1. Intersection (&): Khách hàng mua cả 3 kênh = online & store & mobile
  2. Difference (-): Chỉ mua online = online - store - mobile
  3. Union (|): Tổng khách unique = online | store | mobile
  4. Set tự động loại bỏ duplicate, rất hữu dụng cho phân tích khách hàng!
Đề bài: Dùng Set để phân tích khách hàng mua từ nhiều kênh
Python
1# Khách hàng theo kênh
2online = {"Alice", "Bob", "Charlie", "Diana", "Eve"}
3store = {"Bob", "Frank", "Charlie", "Grace"}
4mobile = {"Alice", "Charlie", "Henry", "Diana"}
5
6# Phân tích
7print(f"Mua online: {len(online)} người")
8print(f"Mua cửa hàng: {len(store)} người")
9print(f"Mua mobile: {len(mobile)} người")
10
11# Mua tất cả kênh
12all_channels = online & store & mobile
13print(f"\nMua cả 3 kênh: {all_channels}") # {'Charlie'}
14
15# Chỉ mua online
16only_online = online - store - mobile
17print(f"Chỉ online: {only_online}") # {'Eve'}
18
19# Tổng khách hàng unique
20total = online | store | mobile
21print(f"Tổng unique: {len(total)} người") # 8

Checkpoint

Bạn đã hiểu sự khác biệt giữa List, Dict, Set, Tuple chưa? Mỗi loại phù hợp với tình huống nào?

4

🔴 Phần 4: Functions Nâng Cao (Hard)

TB5 min

Bài 4.1: Flatten Nested List

💡 Gợi ý
  1. Dùng đệ quy (recursion): Function gọi lại chính nó
  2. Kiểm tra từng phần tử: isinstance(item, list) → gọi đệ quy, ngược lại → append
  3. Base case: Khi item không phải list → dừng đệ quy
  4. One-liner: [x for sublist in lst for x in sublist] (chỉ đệ quy 1 cấp)
Đề bài: Viết function biến list lồng nhau thành list phẳng (bất kỳ độ sâu)
Python
1def flatten(lst):
2 """Flatten list lồng nhau bất kỳ"""
3 result = []
4 for item in lst:
5 if isinstance(item, list):
6 result.extend(flatten(item)) # Đệ quy
7 else:
8 result.append(item)
9 return result
10
11# Test
12nested = [1, [2, 3], [4, [5, 6]], [7, [8, [9]]]]
13print(flatten(nested))
14# [1, 2, 3, 4, 5, 6, 7, 8, 9]
15
16# One-liner (chỉ 1 cấp)
17simple = [[1,2], [3,4], [5]]
18flat = [x for sublist in simple for x in sublist]
19# [1, 2, 3, 4, 5]

Bài 4.2: Decorator — Logging & Retry

💡 Gợi ý
  1. Decorator: Function nhận function, trả về function mới có thêm logic
  2. Pattern: def decorator(func): def wrapper(*args, **kwargs): ... return func(*args, **kwargs) return wrapper
  3. @wraps(func): Giữ nguyên metadata (__name__, __doc__)
  4. Retry: Dùng loop + try/except, time.sleep(delay) giữa các lần thử
  5. Decorator này rất quan trọng khi làm API calls hoặc database connections!
Đề bài: Viết 2 decorators: @log ghi lại mọi lần gọi, @retry thử lại khi lỗi
Python
1import time
2from functools import wraps
3
4def log(func):
5 """Decorator ghi log mỗi lần gọi function"""
6 @wraps(func)
7 def wrapper(*args, **kwargs):
8 args_str = ", ".join(map(str, args))
9 kwargs_str = ", ".join(f"{k}={v}" for k, v in kwargs.items())
10 all_args = ", ".join(filter(None, [args_str, kwargs_str]))
11 print(f"📝 Calling {func.__name__}({all_args})")
12 result = func(*args, **kwargs)
13 print(f"✅ {func.__name__} returned: {result}")
14 return result
15 return wrapper
16
17def retry(max_attempts=3, delay=1):
18 """Decorator thử lại khi gặp lỗi"""
19 def decorator(func):
20 @wraps(func)
21 def wrapper(*args, **kwargs):
22 for attempt in range(1, max_attempts + 1):
23 try:
24 return func(*args, **kwargs)
25 except Exception as e:
26 print(f"⚠️ Attempt {attempt}/{max_attempts} failed: {e}")
27 if attempt < max_attempts:
28 time.sleep(delay)
29 raise Exception(f"Failed after {max_attempts} attempts")
30 return wrapper
31 return decorator
32
33# Test
34@log
35def add(a, b):
36 return a + b
37
38@retry(max_attempts=3, delay=0.5)
39def risky_operation():
40 import random
41 if random.random() < 0.7:
42 raise ConnectionError("Network timeout")
43 return "Success!"
44
45add(3, 5)
46risky_operation()

Bài 4.3: Mini Data Pipeline

💡 Gợi ý
  1. Pipeline ETL: Extract (load) → Transform (clean) → Load (analyze)
  2. Mỗi function chỉ làm 1 việc (Single Responsibility Principle)
  3. Truyền output function này làm input function khác: clean_data(load_data(raw))
  4. Validation: Kiểm tra len(row) == len(header)all(cell.strip())
  5. Pattern này giống Pandas pipeline: df.pipe(clean).pipe(transform).pipe(analyze)
Đề bài: Xây dựng pipeline xử lý dữ liệu dùng functions
Python
1def load_data(raw_data):
2 """Bước 1: Parse raw data"""
3 return [row.split(",") for row in raw_data.strip().split("\n")]
4
5def clean_data(data):
6 """Bước 2: Clean & validate"""
7 header = data[0]
8 cleaned = []
9 for row in data[1:]:
10 if len(row) == len(header) and all(cell.strip() for cell in row):
11 cleaned.append([cell.strip() for cell in row])
12 return header, cleaned
13
14def transform_data(header, data):
15 """Bước 3: Convert to list of dicts"""
16 return [dict(zip(header, row)) for row in data]
17
18def analyze(records):
19 """Bước 4: Tính thống kê"""
20 scores = [float(r["score"]) for r in records]
21 return {
22 "count": len(scores),
23 "mean": sum(scores) / len(scores),
24 "min": min(scores),
25 "max": max(scores),
26 }
27
28# Pipeline
29raw = """name,score,grade
30Alice,95,A
31Bob,87,B
32Charlie,92,A
33Diana,,B
34Eve,78,C"""
35
36data = load_data(raw)
37header, cleaned = clean_data(data)
38records = transform_data(header, cleaned)
39stats = analyze(records)
40
41print(f"Kết quả phân tích ({stats['count']} records):")
42print(f" Mean: {stats['mean']:.1f}")
43print(f" Min: {stats['min']:.0f} | Max: {stats['max']:.0f}")

Bài 4.3 mô phỏng pipeline ETL (Extract-Transform-Load) thực tế mà Data Engineer/Scientist hay làm. Bạn sẽ gặp lại pattern này khi học Pandas!

Checkpoint

Bạn đã giải được ít nhất 1 bài Hard chưa? Bài flatten dùng đệ quy — hãy đảm bảo bạn hiểu cách hoạt động.

5

📝 Tổng Kết

TB5 min

Câu hỏi tự kiểm tra

  1. Trong bài FizzBuzz, bạn cần kiểm tra điều kiện chia hết cho 15 trước hay chia hết cho 3/5 trước? Tại sao?
  2. Pipeline ETL gồm những bước nào? Tại sao mỗi function chỉ nên làm một việc?
  3. Khi viết hàm kiểm tra mật khẩu, những tiêu chí nào cần kiểm tra và bạn dùng string methods nào?
  4. Đệ quy (recursion) hoạt động như thế nào trong bài flatten nested list? Base case là gì?

✅ Checklist hoàn thành

  • 🟢 Phần 1 (Easy): Variables, f-string, BMI calculator — xong?
  • 🟡 Phần 2 (Medium): FizzBuzz, prime numbers, password validator — xong?
  • 🟡 Phần 3 (Medium): Word counter, grade manager, set operations — xong?
  • 🔴 Phần 4 (Hard): Flatten, decorators, data pipeline — xong?

Bảng đánh giá

Mức độHoàn thànhĐánh giá
Phần 1 (Easy)3/3 bàiSẵn sàng tiếp tục ✅
Phần 2 (Medium)≥ 3/4 bàiNền tảng vững
Phần 3 (Medium)≥ 2/3 bàiHiểu Collections tốt
Phần 4 (Hard)≥ 1/3 bàiXuất sắc! 🌟

Bài tiếp theo: NumPy — Nền tảng tính toán khoa học trong Python! 🔢