*args và **kwargs
1. Giới thiệu
Phần tiêu đề “1. Giới thiệu”*args và **kwargs cho phép function nhận số lượng arguments không xác định.
Tại sao cần?
Phần tiêu đề “Tại sao cần?”- ✅ Function linh hoạt hơn
- ✅ Không cần biết trước số lượng parameters
- ✅ Dễ mở rộng
- ✅ Viết wrapper functions
2. *args - Variable Positional Arguments
Phần tiêu đề “2. *args - Variable Positional Arguments”2.1 - Cú pháp
Phần tiêu đề “2.1 - Cú pháp”def function_name(*args): # args là tuple chứa tất cả arguments pass2.2 - Ví dụ cơ bản
Phần tiêu đề “2.2 - Ví dụ cơ bản”def sum_all(*numbers): """Tính tổng tất cả các số""" total = 0 for num in numbers: total += num return total
# Gọi với số lượng arguments khác nhauprint(sum_all(1, 2, 3)) # 6print(sum_all(1, 2, 3, 4, 5)) # 15print(sum_all(10, 20)) # 302.3 - args là tuple
Phần tiêu đề “2.3 - args là tuple”def print_args(*args): print(f"Type: {type(args)}") print(f"Args: {args}") print(f"Length: {len(args)}")
print_args(1, 2, 3, "hello", True)# Type: <class 'tuple'># Args: (1, 2, 3, 'hello', True)# Length: 53. **kwargs - Variable Keyword Arguments
Phần tiêu đề “3. **kwargs - Variable Keyword Arguments”3.1 - Cú pháp
Phần tiêu đề “3.1 - Cú pháp”def function_name(**kwargs): # kwargs là dictionary chứa tất cả keyword arguments pass3.2 - Ví dụ cơ bản
Phần tiêu đề “3.2 - Ví dụ cơ bản”def print_info(**kwargs): """In thông tin dạng key=value""" for key, value in kwargs.items(): print(f"{key}: {value}")
print_info(name="Alice", age=25, city="Hanoi")# name: Alice# age: 25# city: Hanoi
print_info(product="Laptop", price=1000, brand="Dell")# product: Laptop# price: 1000# brand: Dell3.3 - kwargs là dictionary
Phần tiêu đề “3.3 - kwargs là dictionary”def print_kwargs(**kwargs): print(f"Type: {type(kwargs)}") print(f"Kwargs: {kwargs}") print(f"Length: {len(kwargs)}")
print_kwargs(a=1, b=2, c=3)# Type: <class 'dict'># Kwargs: {'a': 1, 'b': 2, 'c': 3}# Length: 34. Kết hợp *args và **kwargs
Phần tiêu đề “4. Kết hợp *args và **kwargs”4.1 - Thứ tự parameters
Phần tiêu đề “4.1 - Thứ tự parameters”def full_function(normal_arg, *args, default_arg="default", **kwargs): print(f"Normal: {normal_arg}") print(f"Args: {args}") print(f"Default: {default_arg}") print(f"Kwargs: {kwargs}")
full_function(1, 2, 3, 4, default_arg="custom", x=10, y=20)# Normal: 1# Args: (2, 3, 4)# Default: custom# Kwargs: {'x': 10, 'y': 20}Thứ tự bắt buộc:
- Positional arguments
*args- Keyword arguments (có default)
**kwargs
4.2 - Ví dụ thực tế
Phần tiêu đề “4.2 - Ví dụ thực tế”def create_user(username, email, *roles, **extra_info): """Tạo user với roles và thông tin bổ sung""" user = { "username": username, "email": email, "roles": list(roles), "extra": extra_info } return user
user = create_user( "alice", "admin", "editor", age=25, city="Hanoi")print(user)# {# 'username': 'alice',# 'email': '[email protected]',# 'roles': ['admin', 'editor'],# 'extra': {'age': 25, 'city': 'Hanoi'}# }5. Unpacking với * và **
Phần tiêu đề “5. Unpacking với * và **”5.1 - Unpacking list/tuple với *
Phần tiêu đề “5.1 - Unpacking list/tuple với *”def add(a, b, c): return a + b + c
numbers = [1, 2, 3]
# ❌ Sai# result = add(numbers) # TypeError
# ✅ Đúng - Unpack listresult = add(*numbers)print(result) # 6
# Tương đương với:result = add(numbers[0], numbers[1], numbers[2])5.2 - Unpacking dictionary với **
Phần tiêu đề “5.2 - Unpacking dictionary với **”def greet(name, age, city): return f"{name}, {age} years old, from {city}"
person = {"name": "Alice", "age": 25, "city": "Hanoi"}
# ✅ Unpack dictionarymessage = greet(**person)print(message)# Alice, 25 years old, from Hanoi
# Tương đương với:message = greet(name="Alice", age=25, city="Hanoi")6. Ví dụ thực tế
Phần tiêu đề “6. Ví dụ thực tế”Ví dụ 1: Wrapper function
Phần tiêu đề “Ví dụ 1: Wrapper function”def log_function_call(func): """Decorator log function calls""" def wrapper(*args, **kwargs): print(f"Calling {func.__name__}") print(f"Args: {args}") print(f"Kwargs: {kwargs}") result = func(*args, **kwargs) print(f"Result: {result}") return result return wrapper
@log_function_calldef calculate(a, b, operation="add"): if operation == "add": return a + b elif operation == "multiply": return a * b
calculate(5, 3, operation="multiply")Ví dụ 2: Flexible configuration
Phần tiêu đề “Ví dụ 2: Flexible configuration”def configure_app(**settings): """Cấu hình ứng dụng""" default_config = { "debug": False, "port": 8000, "host": "localhost" }
# Merge với settings config = {**default_config, **settings} return config
# Sử dụngconfig1 = configure_app(debug=True, port=3000)config2 = configure_app(host="0.0.0.0")print(config1)print(config2)Ví dụ 3: Format string builder
Phần tiêu đề “Ví dụ 3: Format string builder”def build_query(*conditions, **params): """Xây dựng SQL query""" query = "SELECT * FROM users"
if conditions: where_clause = " AND ".join(conditions) query += f" WHERE {where_clause}"
if params: order = params.get("order_by") limit = params.get("limit")
if order: query += f" ORDER BY {order}" if limit: query += f" LIMIT {limit}"
return query
# Sử dụngq1 = build_query("age > 18", "active = true", order_by="name", limit=10)print(q1)# SELECT * FROM users WHERE age > 18 AND active = true ORDER BY name LIMIT 107. Tips và Best Practices
Phần tiêu đề “7. Tips và Best Practices”1. Đặt tên rõ ràng
Phần tiêu đề “1. Đặt tên rõ ràng”# ✅ TỐT - Tên mô tả rõdef process_data(*data_items, **options): pass
# ❌ TRÁNH - Tên chung chungdef process(*args, **kwargs): pass2. Document arguments
Phần tiêu đề “2. Document arguments”def complex_function(*args, **kwargs): """ Xử lý dữ liệu phức tạp.
Args: *args: List of data items to process **kwargs: Configuration options - method (str): Processing method - verbose (bool): Print debug info """ pass3. Validate inputs
Phần tiêu đề “3. Validate inputs”def safe_divide(*numbers, **options): if not numbers: raise ValueError("At least one number required")
result = numbers[0] for num in numbers[1:]: if num == 0: raise ValueError("Cannot divide by zero") result /= num
return result8. Common Patterns
Phần tiêu đề “8. Common Patterns”Pattern 1: Extend existing function
Phần tiêu đề “Pattern 1: Extend existing function”def original_function(a, b): return a + b
def extended_function(a, b, *args, **kwargs): # Giữ hành vi cũ result = original_function(a, b)
# Thêm tính năng mới if args: result += sum(args)
return resultPattern 2: Forward arguments
Phần tiêu đề “Pattern 2: Forward arguments”class BaseClass: def __init__(self, name): self.name = name
class ExtendedClass(BaseClass): def __init__(self, name, *args, **kwargs): # Forward to parent super().__init__(name)
# Handle extra arguments self.extra = args self.options = kwargsPattern 3: Flexible factory
Phần tiêu đề “Pattern 3: Flexible factory”def create_object(obj_type, *args, **kwargs): """Factory tạo objects""" if obj_type == "list": return list(args) elif obj_type == "dict": return dict(**kwargs) elif obj_type == "tuple": return tuple(args)
# Sử dụnglst = create_object("list", 1, 2, 3, 4)dct = create_object("dict", name="Alice", age=25)9. Lỗi thường gặp
Phần tiêu đề “9. Lỗi thường gặp”Lỗi 1: Thứ tự sai
Phần tiêu đề “Lỗi 1: Thứ tự sai”# ❌ SAI - **kwargs phải sau *argsdef wrong_order(**kwargs, *args): pass
# ✅ ĐÚNGdef correct_order(*args, **kwargs): passLỗi 2: Unpack không đúng type
Phần tiêu đề “Lỗi 2: Unpack không đúng type”def func(a, b, c): pass
# ❌ SAI - Unpack dict với *data = {"a": 1, "b": 2, "c": 3}# func(*data) # Chỉ unpack keys!
# ✅ ĐÚNG - Unpack dict với **func(**data)Lỗi 3: Mix positional và keyword
Phần tiêu đề “Lỗi 3: Mix positional và keyword”def func(*args, **kwargs): pass
# ❌ SAI - Keyword arg sau positional khi có *args# func(1, 2, normal=3, 4) # SyntaxError
# ✅ ĐÚNGfunc(1, 2, 4, normal=3)10. Ví dụ tổng hợp
Phần tiêu đề “10. Ví dụ tổng hợp”def advanced_logger(level, *messages, **config): """ Advanced logging function
Args: level: Log level (INFO, WARNING, ERROR) *messages: Variable messages to log **config: Configuration options - timestamp (bool): Include timestamp - file (str): Output file - format (str): Message format """ import datetime
# Configuration include_timestamp = config.get("timestamp", True) output_file = config.get("file") msg_format = config.get("format", "{level}: {message}")
# Build message combined_message = " ".join(str(msg) for msg in messages)
if include_timestamp: ts = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") log_entry = f"[{ts}] {msg_format.format(level=level, message=combined_message)}" else: log_entry = msg_format.format(level=level, message=combined_message)
# Output if output_file: with open(output_file, "a") as f: f.write(log_entry + "\\n") else: print(log_entry)
# Sử dụngadvanced_logger("INFO", "Application", "started", "successfully", timestamp=True)advanced_logger("ERROR", "Database", "connection", "failed", file="app.log")advanced_logger("WARNING", "Low memory", timestamp=False, format="[{level}] {message}")Bài giảng trên YouTube
Phần tiêu đề “Bài giảng trên YouTube”Cập nhật sau
📝 Bài tập thực hành
Phần tiêu đề “📝 Bài tập thực hành”Sau khi học xong bài này, hãy thực hành với các bài tập sau: