🏷️ Enums - Hằng Số Thông Minh
Mục tiêu: Học cách sử dụng Enum để tạo ra các hằng số có ý nghĩa và an toàn! 🎯
🤔 Enum Là Gì?
Enum (Enumeration - Liệt kê) là một cách để tạo ra một tập hợp các hằng số có tên, thay vì sử dụng những con số hoặc chuỗi "ma thuật".
🎭 Ví Dụ Cuộc Sống
Thay vì viết:
# ❌ Magic numbers - khó hiểu
if user_status == 1:
print("User đang hoạt động")
elif user_status == 2:
print("User bị khóa")
elif user_status == 3:
print("User đã xóa")
Ta viết:
# ✅ Enum - rõ ràng và dễ hiểu
if user_status == UserStatus.ACTIVE:
print("User đang hoạt động")
elif user_status == UserStatus.BLOCKED:
print("User bị khóa")
elif user_status == UserStatus.DELETED:
print("User đã xóa")
🚀 Cách Sử Dụng Enum
Import và tạo Enum cơ bản
from enum import Enum
class Color(Enum):
"""Enum cho các màu sắc"""
RED = 1
GREEN = 2
BLUE = 3
YELLOW = 4
BLACK = 5
WHITE = 6
# Sử dụng Enum
print("🎨 DEMO ENUM CƠ BẢN")
print("=" * 30)
# Truy cập thành viên Enum
favorite_color = Color.BLUE
print(f"Màu yêu thích: {favorite_color}")
print(f"Tên: {favorite_color.name}")
print(f"Giá trị: {favorite_color.value}")
# Kiểm tra type
print(f"Type: {type(favorite_color)}")
print(f"Là Color enum? {isinstance(favorite_color, Color)}")
# So sánh
print(f"BLUE == BLUE: {Color.BLUE == Color.BLUE}")
print(f"BLUE == RED: {Color.BLUE == Color.RED}")
print(f"BLUE is BLUE: {Color.BLUE is Color.BLUE}")
Lặp qua Enum
print(f"\n🔄 LẶP QUA ENUM:")
print("-" * 20)
# Lặp qua tất cả thành viên
for color in Color:
print(f"🎨 {color.name}: {color.value}")
# Lấy danh sách tên và giá trị
color_names = [color.name for color in Color]
color_values = [color.value for color in Color]
print(f"\nTên các màu: {color_names}")
print(f"Giá trị các màu: {color_values}")
🎮 Ví Dụ Game: Character Classes
from enum import Enum, auto
class CharacterClass(Enum):
"""Enum cho các class nhân vật game"""
WARRIOR = auto() # auto() tự động gán giá trị
MAGE = auto()
ARCHER = auto()
HEALER = auto()
ROGUE = auto()
class Difficulty(Enum):
"""Enum cho độ khó"""
EASY = ("Dễ", 1.0, "🟢")
NORMAL = ("Bình thường", 1.5, "🟡")
HARD = ("Khó", 2.0, "🟠")
NIGHTMARE = ("Ác mộng", 3.0, "🔴")
def __init__(self, vietnamese_name, multiplier, icon):
self.vietnamese_name = vietnamese_name
self.multiplier = multiplier
self.icon = icon
class GameCharacter:
"""Class nhân vật game sử dụng Enum"""
def __init__(self, name, character_class, difficulty):
self.name = name
self.character_class = character_class
self.difficulty = difficulty
self.level = 1
self.base_stats = self._get_base_stats()
def _get_base_stats(self):
"""Lấy stats cơ bản theo class"""
base_stats = {
CharacterClass.WARRIOR: {"hp": 120, "mp": 30, "attack": 25, "defense": 20},
CharacterClass.MAGE: {"hp": 80, "mp": 100, "attack": 35, "defense": 10},
CharacterClass.ARCHER: {"hp": 95, "mp": 50, "attack": 30, "defense": 15},
CharacterClass.HEALER: {"hp": 100, "mp": 120, "attack": 18, "defense": 15},
CharacterClass.ROGUE: {"hp": 90, "mp": 60, "attack": 28, "defense": 12}
}
stats = base_stats[self.character_class].copy()
# Áp dụng multiplier từ difficulty
for stat in ['hp', 'attack']:
stats[stat] = int(stats[stat] * self.difficulty.multiplier)
return stats
def get_class_description(self):
"""Mô tả class"""
descriptions = {
CharacterClass.WARRIOR: "🛡️ Chiến binh dũng mãnh với khả năng phòng thủ cao",
CharacterClass.MAGE: "🔮 Pháp sư quyền năng với phép thuật hủy diệt",
CharacterClass.ARCHER: "🏹 Cung thủ thiện xạ với tấn công tầm xa",
CharacterClass.HEALER: "✨ Thầy thuốc với khả năng hồi phục kỳ diệu",
CharacterClass.ROGUE: "🗡️ Sát thủ nhanh nhẹn với đòn tấn công bất ngờ"
}
return descriptions[self.character_class]
def __str__(self):
return (f"{self.difficulty.icon} {self.name} - {self.character_class.name.title()} "
f"(Level {self.level}, {self.difficulty.vietnamese_name})")
def show_stats(self):
"""Hiển thị stats chi tiết"""
print(f"\n👤 {self.name}")
print(f"🎭 Class: {self.character_class.name.title()}")
print(f"⚔️ Difficulty: {self.difficulty.vietnamese_name} {self.difficulty.icon}")
print(f"📊 Stats:")
for stat_name, value in self.base_stats.items():
print(f" {stat_name.upper()}: {value}")
print(f"📝 {self.get_class_description()}")
# Demo Game Character với Enum
print(f"\n🎮 DEMO GAME CHARACTER VỚI ENUM")
print("=" * 50)
# Tạo các nhân vật khác nhau
characters = [
GameCharacter("Arthur", CharacterClass.WARRIOR, Difficulty.NORMAL),
GameCharacter("Merlin", CharacterClass.MAGE, Difficulty.HARD),
GameCharacter("Robin", CharacterClass.ARCHER, Difficulty.EASY),
GameCharacter("Gandalf", CharacterClass.HEALER, Difficulty.NIGHTMARE),
GameCharacter("Shadow", CharacterClass.ROGUE, Difficulty.HARD)
]
# Hiển thị danh sách nhân vật
print("🏆 PARTY MEMBERS:")
for char in characters:
print(f" {char}")
# Hiển thị stats chi tiết của một nhân vật
characters[0].show_stats()
📅 Enum cho Ngày Tháng
from enum import Enum
from datetime import datetime, timedelta
class DayOfWeek(Enum):
"""Enum cho các ngày trong tuần"""
MONDAY = (1, "Thứ Hai", "T2", "📅")
TUESDAY = (2, "Thứ Ba", "T3", "📅")
WEDNESDAY = (3, "Thứ Tư", "T4", "📅")
THURSDAY = (4, "Thứ Năm", "T5", "📅")
FRIDAY = (5, "Thứ Sáu", "T6", "🎉") # Friday emoji khác
SATURDAY = (6, "Thứ Bảy", "T7", "🏖️")
SUNDAY = (7, "Chủ Nhật", "CN", "😴")
def __init__(self, number, vietnamese_name, short_name, emoji):
self.number = number
self.vietnamese_name = vietnamese_name
self.short_name = short_name
self.emoji = emoji
@classmethod
def from_datetime(cls, dt):
"""Tạo DayOfWeek từ datetime"""
# datetime.weekday() trả về 0-6 (Monday=0)
# Ta cần 1-7 (Monday=1)
weekday_map = {
0: cls.MONDAY,
1: cls.TUESDAY,
2: cls.WEDNESDAY,
3: cls.THURSDAY,
4: cls.FRIDAY,
5: cls.SATURDAY,
6: cls.SUNDAY
}
return weekday_map[dt.weekday()]
def is_weekend(self):
"""Kiểm tra có phải cuối tuần không"""
return self in [DayOfWeek.SATURDAY, DayOfWeek.SUNDAY]
def is_workday(self):
"""Kiểm tra có phải ngày làm việc không"""
return not self.is_weekend()
class Month(Enum):
"""Enum cho các tháng"""
JANUARY = (1, "Tháng Một", "❄️")
FEBRUARY = (2, "Tháng Hai", "💝")
MARCH = (3, "Tháng Ba", "🌸")
APRIL = (4, "Tháng Tư", "🌷")
MAY = (5, "Tháng Năm", "🌺")
JUNE = (6, "Tháng Sáu", "☀️")
JULY = (7, "Tháng Bảy", "🏖️")
AUGUST = (8, "Tháng Tám", "🌻")
SEPTEMBER = (9, "Tháng Chín", "🍂")
OCTOBER = (10, "Tháng Mười", "🎃")
NOVEMBER = (11, "Tháng Mười Một", "🦃")
DECEMBER = (12, "Tháng Mười Hai", "🎄")
def __init__(self, number, vietnamese_name, emoji):
self.number = number
self.vietnamese_name = vietnamese_name
self.emoji = emoji
@classmethod
def from_number(cls, month_number):
"""Tạo Month từ số tháng"""
for month in cls:
if month.number == month_number:
return month
raise ValueError(f"Invalid month number: {month_number}")
def get_season(self):
"""Lấy mùa"""
if self.number in [12, 1, 2]:
return "Mùa đông ❄️"
elif self.number in [3, 4, 5]:
return "Mùa xuân 🌸"
elif self.number in [6, 7, 8]:
return "Mùa hè ☀️"
else:
return "Mùa thu 🍂"
# Demo Date Enums
print(f"\n📅 DEMO DATE ENUMS")
print("=" * 30)
# Hôm nay
today = datetime.now()
current_day = DayOfWeek.from_datetime(today)
current_month = Month.from_number(today.month)
print(f"🗓️ Hôm nay:")
print(f" Ngày: {current_day.emoji} {current_day.vietnamese_name}")
print(f" Tháng: {current_month.emoji} {current_month.vietnamese_name}")
print(f" Mùa: {current_month.get_season()}")
print(f" Weekend? {'Có' if current_day.is_weekend() else 'Không'}")
print(f" Ngày làm việc? {'Có' if current_day.is_workday() else 'Không'}")
# Lịch tuần
print(f"\n📆 LỊCH TUẦN:")
for day in DayOfWeek:
status = "🏖️ Nghỉ" if day.is_weekend() else "💼 Làm việc"
print(f" {day.emoji} {day.short_name}: {status}")