Skip to content

🔀 4.5 Ép kiểu dữ liệu

📖 Giới thiệu

Ép kiểu (Type casting/Type conversion) là quá trình chuyển đổi dữ liệu từ kiểu này sang kiểu khác. Trong Python, việc ép kiểu rất quan trọng khi xử lý input từ người dùng, đọc file, hoặc làm việc với API. Hiểu rõ cách ép kiểu sẽ giúp bạn tránh lỗi và xử lý dữ liệu hiệu quả.

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

  • Hiểu khái niệm ép kiểu và tại sao cần thiết
  • Thành thạo các hàm ép kiểu cơ bản trong Python
  • Biết cách xử lý lỗi khi ép kiểu
  • Ứng dụng ép kiểu trong các tình huống thực tế

🔧 Cú pháp

Hàm ép kiểu cơ bản:

python
# Ép sang số nguyên
so_nguyen = int(gia_tri)

# Ép sang số thực
so_thuc = float(gia_tri)

# Ép sang chuỗi
chuoi = str(gia_tri)

# Ép sang boolean
logic = bool(gia_tri)

# Ép sang list
danh_sach = list(gia_tri)

# Ép sang tuple
bo = tuple(gia_tri)

Ép kiểu với xử lý lỗi:

python
try:
    ket_qua = int(input_str)
except ValueError:
    print("Không thể chuyển đổi!")

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

1. 🔢 Ép kiểu sang số

String → Integer:

python
# Thành công
print(int("123"))      # 123
print(int("-45"))      # -45
print(int("0"))        # 0

# Với base khác
print(int("1010", 2))  # 10 (từ nhị phân)
print(int("FF", 16))   # 255 (từ hex)
print(int("77", 8))    # 63 (từ octal)

# Lỗi
try:
    print(int("12.5"))     # ValueError: invalid literal
except ValueError as e:
    print(f"Lỗi: {e}")

try:
    print(int("abc"))      # ValueError: invalid literal
except ValueError as e:
    print(f"Lỗi: {e}")

String → Float:

python
# Thành công
print(float("123"))     # 123.0
print(float("12.5"))    # 12.5
print(float("-3.14"))   # -3.14
print(float("1e6"))     # 1000000.0 (scientific notation)

# Lỗi
try:
    print(float("abc"))    # ValueError
except ValueError as e:
    print(f"Lỗi: {e}")

Float → Integer:

python
# Cắt bỏ phần thập phân (không làm tròn)
print(int(3.14))       # 3
print(int(3.99))       # 3
print(int(-2.7))       # -2

# Để làm tròn, dùng round()
print(round(3.14))     # 3
print(round(3.99))     # 4
print(int(round(3.99))) # 4

2. 🔤 Ép kiểu sang chuỗi

Mọi kiểu → String:

python
# Số → chuỗi
print(str(123))        # "123"
print(str(3.14))       # "3.14"
print(str(True))       # "True"

# Container → chuỗi
print(str([1, 2, 3]))  # "[1, 2, 3]"
print(str({"a": 1}))   # "{'a': 1}"

# Đặc biệt với None
print(str(None))       # "None"

Định dạng số thành chuỗi:

python
# Với f-string (khuyến nghị)
so = 123.456
print(f"{so:.2f}")     # "123.46"
print(f"{so:,}")       # "123.456" (có thể khác tùy locale)

# Với format()
print("{:.2f}".format(so))  # "123.46"

# Với % formatting (cũ)
print("%.2f" % so)     # "123.46"

3. ✅ Ép kiểu sang boolean

Quy tắc chuyển đổi:

python
# Falsy values → False
print(bool(0))         # False
print(bool(0.0))       # False
print(bool(""))        # False
print(bool([]))        # False
print(bool({}))        # False
print(bool(None))      # False

# Truthy values → True
print(bool(1))         # True
print(bool(-1))        # True
print(bool("hello"))   # True
print(bool([1]))       # True
print(bool({"a": 1}))  # True

# Chuỗi đặc biệt
print(bool("0"))       # True (chuỗi không rỗng)
print(bool("False"))   # True (chuỗi không rỗng)

Chuyển chuỗi thành boolean có ý nghĩa:

python
def str_to_bool(value):
    """Chuyển chuỗi thành boolean có ý nghĩa"""
    if isinstance(value, bool):
        return value
    
    if isinstance(value, str):
        return value.lower() in ['true', '1', 'yes', 'on', 'y']
    
    return bool(value)

# Test
print(str_to_bool("true"))     # True
print(str_to_bool("false"))    # False
print(str_to_bool("yes"))      # True
print(str_to_bool("no"))       # False
print(str_to_bool("1"))        # True
print(str_to_bool("0"))        # False

4. 📦 Ép kiểu container

List ↔ Tuple:

python
# List → Tuple
my_list = [1, 2, 3]
my_tuple = tuple(my_list)
print(my_tuple)        # (1, 2, 3)

# Tuple → List
my_tuple = (1, 2, 3)
my_list = list(my_tuple)
print(my_list)         # [1, 2, 3]

String ↔ List:

python
# String → List (ký tự)
text = "hello"
char_list = list(text)
print(char_list)       # ['h', 'e', 'l', 'l', 'o']

# String → List (từ)
sentence = "hello world python"
word_list = sentence.split()
print(word_list)       # ['hello', 'world', 'python']

# List → String
char_list = ['h', 'e', 'l', 'l', 'o']
text = ''.join(char_list)
print(text)            # "hello"

word_list = ['hello', 'world', 'python']
sentence = ' '.join(word_list)
print(sentence)        # "hello world python"

Set operations:

python
# List → Set (loại bỏ duplicate)
numbers = [1, 2, 2, 3, 3, 3]
unique_numbers = set(numbers)
print(unique_numbers)  # {1, 2, 3}

# Set → List
unique_set = {3, 1, 2}
sorted_list = sorted(list(unique_set))
print(sorted_list)     # [1, 2, 3]

5. ⚠️ Xử lý lỗi khi ép kiểu

Try-except cơ bản:

python
def safe_int(value, default=0):
    """Chuyển đổi an toàn sang int"""
    try:
        return int(value)
    except ValueError:
        return default
    except TypeError:
        return default

# Test
print(safe_int("123"))      # 123
print(safe_int("abc"))      # 0
print(safe_int(None))       # 0
print(safe_int("12.5"))     # 0

Validation trước khi ép kiểu:

python
def is_valid_int(value):
    """Kiểm tra có thể chuyển thành int không"""
    try:
        int(value)
        return True
    except (ValueError, TypeError):
        return False

def is_valid_float(value):
    """Kiểm tra có thể chuyển thành float không"""
    try:
        float(value)
        return True
    except (ValueError, TypeError):
        return False

# Test
print(is_valid_int("123"))   # True
print(is_valid_int("12.5"))  # False
print(is_valid_float("12.5")) # True

💻 Ví dụ minh họa

Ví dụ 1: Calculator với input validation

python
# calculator_safe.py
print("🧮 MÁY TÍNH AN TOÀN")
print("=" * 25)

def safe_number_input(prompt, number_type=float):
    """Nhập số an toàn với validation"""
    while True:
        try:
            user_input = input(prompt).strip()
            
            # Kiểm tra input rỗng
            if not user_input:
                print("❌ Vui lòng nhập một số!")
                continue
            
            # Thử chuyển đổi
            number = number_type(user_input)
            return number
            
        except ValueError:
            type_name = "số nguyên" if number_type == int else "số"
            print(f"❌ '{user_input}' không phải là {type_name} hợp lệ!")
        except KeyboardInterrupt:
            print("\n👋 Tạm biệt!")
            exit()

def safe_operator_input():
    """Nhập toán tử an toàn"""
    valid_operators = ['+', '-', '*', '/', '//', '%', '**']
    
    while True:
        operator = input("🔢 Nhập toán tử (+, -, *, /, //, %, **): ").strip()
        
        if operator in valid_operators:
            return operator
        else:
            print(f"❌ Toán tử không hợp lệ! Chọn từ: {', '.join(valid_operators)}")

def calculate(num1, operator, num2):
    """Thực hiện phép tính với xử lý lỗi"""
    try:
        if operator == '+':
            return num1 + num2, None
        elif operator == '-':
            return num1 - num2, None
        elif operator == '*':
            return num1 * num2, None
        elif operator == '/':
            if num2 == 0:
                return None, "Không thể chia cho 0!"
            return num1 / num2, None
        elif operator == '//':
            if num2 == 0:
                return None, "Không thể chia cho 0!"
            return num1 // num2, None
        elif operator == '%':
            if num2 == 0:
                return None, "Không thể chia cho 0!"
            return num1 % num2, None
        elif operator == '**':
            # Giới hạn lũy thừa để tránh tràn số
            if abs(num2) > 1000:
                return None, "Số mũ quá lớn!"
            return num1 ** num2, None
    except OverflowError:
        return None, "Kết quả quá lớn!"
    except Exception as e:
        return None, f"Lỗi tính toán: {e}"

def format_result(result):
    """Định dạng kết quả đẹp"""
    if isinstance(result, float):
        # Nếu là số nguyên trong float
        if result.is_integer():
            return str(int(result))
        # Làm tròn đến 10 chữ số thập phân
        return f"{result:.10g}"
    return str(result)

# Chương trình chính
print("💡 Nhập 'quit' để thoát")

while True:
    print("\n" + "="*30)
    
    # Nhập số thứ nhất
    num1_input = input("🔢 Số thứ nhất: ").strip()
    if num1_input.lower() == 'quit':
        break
    
    try:
        num1 = float(num1_input)
    except ValueError:
        print("❌ Số thứ nhất không hợp lệ!")
        continue
    
    # Nhập toán tử
    operator = safe_operator_input()
    
    # Nhập số thứ hai
    num2 = safe_number_input("🔢 Số thứ hai: ")
    
    # Tính toán
    result, error = calculate(num1, operator, num2)
    
    # Hiển thị kết quả
    print(f"\n🎯 KẾT QUẢ:")
    if error:
        print(f"❌ {error}")
    else:
        formatted_result = format_result(result)
        print(f"✅ {format_result(num1)} {operator} {format_result(num2)} = {formatted_result}")
        
        # Thông tin thêm về kiểu dữ liệu
        print(f"📊 Kiểu kết quả: {type(result).__name__}")

print("\n👋 Cảm ơn bạn đã sử dụng máy tính!")

Ví dụ 2: Data parser từ file CSV

python
# csv_parser.py
print("📊 CSV DATA PARSER")
print("=" * 25)

class DataConverter:
    """Class để chuyển đổi dữ liệu từ CSV"""
    
    @staticmethod
    def auto_convert(value):
        """Tự động detect và convert kiểu dữ liệu"""
        value = value.strip()
        
        # Kiểm tra None/empty
        if not value or value.lower() in ['none', 'null', 'na', '']:
            return None
        
        # Kiểm tra boolean
        if value.lower() in ['true', 'false', 'yes', 'no']:
            return value.lower() in ['true', 'yes']
        
        # Kiểm tra số nguyên
        if value.isdigit() or (value.startswith('-') and value[1:].isdigit()):
            return int(value)
        
        # Kiểm tra số thực
        try:
            if '.' in value or 'e' in value.lower():
                return float(value)
        except ValueError:
            pass
        
        # Mặc định là string
        return value
    
    @staticmethod
    def convert_with_type(value, target_type):
        """Convert với kiểu đã chỉ định"""
        value = value.strip()
        
        if not value:
            return None
        
        try:
            if target_type == 'int':
                return int(float(value))  # Cho phép "12.0" → 12
            elif target_type == 'float':
                return float(value)
            elif target_type == 'bool':
                return value.lower() in ['true', '1', 'yes', 'on']
            elif target_type == 'str':
                return str(value)
            else:
                return value
        except (ValueError, TypeError):
            return value  # Trả về original nếu không convert được

def parse_csv_line(line, column_types=None):
    """Parse một dòng CSV"""
    # Tách dữ liệu (đơn giản, không xử lý quotes phức tạp)
    values = [v.strip() for v in line.split(',')]
    
    if column_types:
        # Convert theo kiểu đã chỉ định
        converted = []
        for i, value in enumerate(values):
            if i < len(column_types):
                converted.append(DataConverter.convert_with_type(value, column_types[i]))
            else:
                converted.append(DataConverter.auto_convert(value))
        return converted
    else:
        # Auto detect
        return [DataConverter.auto_convert(value) for value in values]

def analyze_data_types(data):
    """Phân tích kiểu dữ liệu trong dataset"""
    if not data:
        return {}
    
    type_analysis = {}
    num_columns = len(data[0]) if data else 0
    
    for col_idx in range(num_columns):
        types_in_column = set()
        
        for row in data:
            if col_idx < len(row) and row[col_idx] is not None:
                types_in_column.add(type(row[col_idx]).__name__)
        
        type_analysis[f"Column_{col_idx + 1}"] = list(types_in_column)
    
    return type_analysis

# Demo với dữ liệu mẫu
print("📝 Demo với dữ liệu CSV mẫu:")

sample_csv = """Name,Age,Score,Passed,Salary
John,25,8.5,True,50000.50
Jane,30,9.2,yes,65000
Bob,22,7.8,false,45000.25
Alice,28,null,True,55000.0
Mike,35,6.5,no,"""

print("\n📄 Dữ liệu CSV:")
print(sample_csv)

# Parse dữ liệu
lines = sample_csv.strip().split('\n')
headers = [h.strip() for h in lines[0].split(',')]
data_rows = []

print(f"\n🔄 Parsing {len(lines) - 1} dòng dữ liệu...")

for line in lines[1:]:
    parsed_row = parse_csv_line(line)
    data_rows.append(parsed_row)

# Hiển thị kết quả
print(f"\n📊 KẾT QUẢ PARSING:")
print("-" * 50)

for i, header in enumerate(headers):
    print(f"📋 {header}:")
    for j, row in enumerate(data_rows):
        value = row[i] if i < len(row) else None
        type_name = type(value).__name__ if value is not None else "NoneType"
        print(f"  Row {j+1}: {value} ({type_name})")
    print()

# Phân tích kiểu dữ liệu
type_analysis = analyze_data_types(data_rows)
print("🔍 PHÂN TÍCH KIỂU DỮ LIỆU:")
print("-" * 30)
for col_name, types in type_analysis.items():
    header_name = headers[int(col_name.split('_')[1]) - 1]
    print(f"{header_name}: {', '.join(types)}")

# Demo convert với kiểu chỉ định
print(f"\n🎯 DEMO CONVERT VỚI KIỂU CHỈ ĐỊNH:")
print("-" * 40)

column_types = ['str', 'int', 'float', 'bool', 'float']
print(f"Kiểu chỉ định: {column_types}")

for i, line in enumerate(lines[1:], 1):
    converted = parse_csv_line(line, column_types)
    print(f"Row {i}: {converted}")
    
    # Hiển thị kiểu của từng element
    types_str = [type(v).__name__ for v in converted]
    print(f"Types: {types_str}")
    print()

Ví dụ 3: Configuration parser

python
# config_parser.py
print("⚙️ CONFIGURATION PARSER")
print("=" * 30)

class ConfigParser:
    """Parser cho file config đơn giản"""
    
    def __init__(self):
        self.config = {}
    
    def parse_value(self, value_str):
        """Parse giá trị từ string với type detection"""
        value = value_str.strip()
        
        # Remove quotes
        if (value.startswith('"') and value.endswith('"')) or \
           (value.startswith("'") and value.endswith("'")):
            return value[1:-1]  # String trong quotes
        
        # Boolean
        if value.lower() in ['true', 'false']:
            return value.lower() == 'true'
        
        # None/null
        if value.lower() in ['none', 'null']:
            return None
        
        # List (simple format: [1,2,3])
        if value.startswith('[') and value.endswith(']'):
            list_content = value[1:-1].strip()
            if not list_content:
                return []
            
            items = []
            for item in list_content.split(','):
                items.append(self.parse_value(item.strip()))
            return items
        
        # Number
        try:
            # Try int first
            if '.' not in value and 'e' not in value.lower():
                return int(value)
            else:
                return float(value)
        except ValueError:
            pass
        
        # Default to string
        return value
    
    def parse_line(self, line):
        """Parse một dòng config"""
        line = line.strip()
        
        # Skip empty lines and comments
        if not line or line.startswith('#') or line.startswith('//'):
            return None, None
        
        # Split key = value
        if '=' not in line:
            return None, None
        
        key, value = line.split('=', 1)
        key = key.strip()
        value = value.strip()
        
        return key, self.parse_value(value)
    
    def parse_config(self, config_text):
        """Parse toàn bộ config"""
        self.config = {}
        
        for line_num, line in enumerate(config_text.split('\n'), 1):
            try:
                key, value = self.parse_line(line)
                if key is not None:
                    self.config[key] = value
            except Exception as e:
                print(f"⚠️ Lỗi dòng {line_num}: {e}")
        
        return self.config
    
    def get(self, key, default=None, expected_type=None):
        """Get config value với type checking"""
        value = self.config.get(key, default)
        
        if expected_type and value is not None:
            if not isinstance(value, expected_type):
                try:
                    # Thử convert
                    if expected_type == int:
                        value = int(float(str(value)))
                    elif expected_type == float:
                        value = float(value)
                    elif expected_type == str:
                        value = str(value)
                    elif expected_type == bool:
                        if isinstance(value, str):
                            value = value.lower() in ['true', '1', 'yes', 'on']
                        else:
                            value = bool(value)
                except (ValueError, TypeError):
                    print(f"⚠️ Không thể convert {key} sang {expected_type.__name__}")
                    value = default
        
        return value

# Demo
sample_config = """
# Database configuration
db_host = localhost
db_port = 5432
db_name = "my_database"
db_user = admin
db_password = 'secret123'
db_ssl = true

# Application settings
app_name = "My Python App"
app_version = 1.2.5
debug_mode = false
max_connections = 100
timeout = 30.5

# Features
enabled_features = [auth, logging, caching]
admin_emails = ["admin@example.com", "support@example.com"]

# Optional settings
cache_ttl = none
log_level = INFO
"""

print("📄 Sample config file:")
print(sample_config)

# Parse config
parser = ConfigParser()
config = parser.parse_config(sample_config)

print("\n🔄 Parsed configuration:")
print("-" * 30)
for key, value in config.items():
    value_type = type(value).__name__
    print(f"{key} = {value} ({value_type})")

print(f"\n🎯 SỬNG DỤNG CONFIG:")
print("-" * 25)

# Sử dụng config với type checking
db_host = parser.get('db_host', 'localhost', str)
db_port = parser.get('db_port', 5432, int)
debug_mode = parser.get('debug_mode', False, bool)
timeout = parser.get('timeout', 30.0, float)
admin_emails = parser.get('admin_emails', [], list)

print(f"🔗 Database: {db_host}:{db_port}")
print(f"🐛 Debug mode: {debug_mode}")
print(f"⏱️ Timeout: {timeout}s")
print(f"👥 Admin emails: {len(admin_emails)} addresses")

# Validation example
required_settings = ['db_host', 'db_port', 'app_name']
missing_settings = []

for setting in required_settings:
    if setting not in config:
        missing_settings.append(setting)

if missing_settings:
    print(f"\n❌ Missing required settings: {missing_settings}")
else:
    print(f"\n✅ All required settings present!")

# Type conversion demo
print(f"\n🔄 TYPE CONVERSION DEMO:")
print("-" * 30)

test_values = [
    ("123", int),
    ("12.5", float),
    ("true", bool),
    ("hello", str),
    ("[1,2,3]", list)
]

for value_str, target_type in test_values:
    parsed = parser.parse_value(value_str)
    print(f"'{value_str}' → {parsed} ({type(parsed).__name__})")
    
    if target_type and not isinstance(parsed, target_type):
        print(f"  ⚠️ Expected {target_type.__name__}, got {type(parsed).__name__}")
    else:
        print(f"  ✅ Correct type")

🏋️ Thực hành

Bài tập 1: Universal converter

Nhiệm vụ: Tạo tool chuyển đổi đa năng

python
# TODO: Tạo converter có thể:
# - Tự động detect kiểu input
# - Convert sang kiểu mong muốn
# - Xử lý lỗi gracefully
# - Hỗ trợ nhiều định dạng

Đáp án:

python
# universal_converter.py
import json
import ast

class UniversalConverter:
    def __init__(self):
        self.conversion_history = []
    
    def detect_type(self, value_str):
        """Tự động detect kiểu dữ liệu"""
        value = value_str.strip()
        
        # JSON
        try:
            parsed = json.loads(value)
            return 'json', parsed
        except:
            pass
        
        # Python literal
        try:
            parsed = ast.literal_eval(value)
            return 'literal', parsed
        except:
            pass
        
        # Boolean
        if value.lower() in ['true', 'false', 'yes', 'no']:
            return 'bool', value.lower() in ['true', 'yes']
        
        # Number
        try:
            if '.' in value:
                return 'float', float(value)
            else:
                return 'int', int(value)
        except:
            pass
        
        return 'str', value
    
    def convert_to(self, value, target_type):
        """Convert giá trị sang kiểu đích"""
        try:
            if target_type == 'int':
                if isinstance(value, str):
                    # Remove commas from numbers
                    clean_value = value.replace(',', '')
                    return int(float(clean_value))
                return int(value)
            
            elif target_type == 'float':
                if isinstance(value, str):
                    clean_value = value.replace(',', '')
                    return float(clean_value)
                return float(value)
            
            elif target_type == 'str':
                return str(value)
            
            elif target_type == 'bool':
                if isinstance(value, str):
                    return value.lower() in ['true', '1', 'yes', 'on', 'y']
                return bool(value)
            
            elif target_type == 'list':
                if isinstance(value, str):
                    # Try different formats
                    if value.startswith('[') and value.endswith(']'):
                        return ast.literal_eval(value)
                    else:
                        return value.split(',')
                return list(value)
            
            elif target_type == 'json':
                return json.dumps(value, ensure_ascii=False, indent=2)
            
        except Exception as e:
            raise ValueError(f"Cannot convert to {target_type}: {e}")

converter = UniversalConverter()

print("🔄 UNIVERSAL CONVERTER")
print("=" * 25)

while True:
    print("\nInput (or 'quit' to exit):")
    user_input = input(">>> ").strip()
    
    if user_input.lower() == 'quit':
        break
    
    # Detect input type
    detected_type, detected_value = converter.detect_type(user_input)
    print(f"🔍 Detected: {detected_type} = {detected_value}")
    
    # Show conversion options
    print("\nConvert to:")
    print("1. int    2. float   3. str     4. bool")
    print("5. list   6. json    7. auto    8. skip")
    
    choice = input("Choice: ").strip()
    
    conversions = {
        '1': 'int', '2': 'float', '3': 'str', 
        '4': 'bool', '5': 'list', '6': 'json'
    }
    
    if choice in conversions:
        try:
            result = converter.convert_to(detected_value, conversions[choice])
            print(f"✅ Result: {result} ({type(result).__name__})")
        except Exception as e:
            print(f"❌ Error: {e}")
    elif choice == '7':
        print(f"Auto: {detected_value} ({type(detected_value).__name__})")

Bài tập 2: Data validator

Nhiệm vụ: Tạo hệ thống validate và convert dữ liệu

python
# TODO: Validator với rules:
# - Required fields
# - Type constraints  
# - Range validation
# - Custom validators

Đáp án:

python
# data_validator.py
class DataValidator:
    def __init__(self):
        self.rules = {}
    
    def add_rule(self, field, **kwargs):
        """Thêm rule cho field"""
        self.rules[field] = kwargs
    
    def validate(self, data):
        """Validate dữ liệu theo rules"""
        errors = []
        cleaned_data = {}
        
        for field, rules in self.rules.items():
            value = data.get(field)
            
            # Required check
            if rules.get('required', False) and not value:
                errors.append(f"{field} is required")
                continue
            
            if value is None:
                cleaned_data[field] = rules.get('default')
                continue
            
            # Type conversion
            target_type = rules.get('type')
            if target_type:
                try:
                    if target_type == int:
                        value = int(float(str(value)))
                    elif target_type == float:
                        value = float(value)
                    elif target_type == str:
                        value = str(value)
                    elif target_type == bool:
                        if isinstance(value, str):
                            value = value.lower() in ['true', '1', 'yes']
                        else:
                            value = bool(value)
                except (ValueError, TypeError):
                    errors.append(f"{field} must be {target_type.__name__}")
                    continue
            
            # Range validation
            if 'min' in rules and value < rules['min']:
                errors.append(f"{field} must be >= {rules['min']}")
            if 'max' in rules and value > rules['max']:
                errors.append(f"{field} must be <= {rules['max']}")
            
            # Custom validator
            if 'validator' in rules:
                try:
                    if not rules['validator'](value):
                        msg = rules.get('error_msg', f"{field} validation failed")
                        errors.append(msg)
                except Exception as e:
                    errors.append(f"{field} validation error: {e}")
            
            cleaned_data[field] = value
        
        return cleaned_data, errors

# Demo
validator = DataValidator()
validator.add_rule('name', required=True, type=str)
validator.add_rule('age', required=True, type=int, min=0, max=150)
validator.add_rule('email', required=True, type=str, 
                  validator=lambda x: '@' in x and '.' in x,
                  error_msg="Invalid email format")
validator.add_rule('salary', type=float, min=0, default=0.0)

test_data = {
    'name': 'John Doe',
    'age': '25',
    'email': 'john@example.com',
    'salary': '50000.5'
}

cleaned, errors = validator.validate(test_data)
print("✅ Cleaned:", cleaned)
print("❌ Errors:", errors)

📋 Tóm tắt

Hàm ép kiểu cơ bản:

HàmMục đíchVí dụLưu ý
int()→ số nguyênint("123")123Cắt phần thập phân
float()→ số thựcfloat("12.5")12.5Chấp nhận scientific notation
str()→ chuỗistr(123)"123"Luôn thành công
bool()→ booleanbool("hello")TrueTheo quy tắc truthy/falsy
list()→ listlist("abc")['a','b','c']Iterable → list
tuple()→ tupletuple([1,2])(1,2)Iterable → tuple

Xử lý lỗi phổ biến:

python
# Safe conversion với try-except
try:
    result = int(user_input)
except ValueError:
    print("Không phải số nguyên!")

# Helper function
def safe_int(value, default=0):
    try:
        return int(value)
    except (ValueError, TypeError):
        return default

# Validation trước khi convert
if value.isdigit():
    number = int(value)

Patterns thường dùng:

python
# Input validation
def get_positive_int(prompt):
    while True:
        try:
            value = int(input(prompt))
            if value > 0:
                return value
            print("Phải là số dương!")
        except ValueError:
            print("Phải là số nguyên!")

# Auto type detection
def smart_convert(value):
    try:
        return int(value)
    except ValueError:
        try:
            return float(value)
        except ValueError:
            return str(value)

# Multiple type conversion
def convert_list(values, target_type):
    return [target_type(v) for v in values if v]

Best practices:

  1. 🛡️ Luôn validate input trước khi ép kiểu
  2. ⚠️ Sử dụng try-except cho conversion có thể fail
  3. 🎯 Cung cấp default values hợp lý
  4. 📝 Clear error messages để debug dễ dàng
  5. 🔄 Chain conversions khi cần: int(float("12.5"))

Truthy/Falsy reminder:

python
# Falsy values
bool(0), bool(0.0), bool(""), bool([]), bool({}), bool(None)
# → All False

# Everything else is Truthy
bool(1), bool("0"), bool([0]), bool({0: 0})
# → All True

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

Bài tiếp theo sẽ học về ✔️ if cơ bản - cách ra quyết định trong chương trình Python!


💡 Mẹo: Ép kiểu là skill quan trọng để xử lý dữ liệu từ nhiều nguồn khác nhau. Luôn nhớ validate và handle errors!

🔄 Thực hành: Thử tạo một data parser cho format bạn thường gặp (JSON, CSV, XML) để hiểu rõ ép kiểu trong thực tế!

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