Thông báo: Download 4 khóa học Python từ cơ bản đến nâng cao tại đây.
Cách sử dụng Protocol trong Python
Trong bài viết này, bạn sẽ tìm hiểu về Python Protocol, một tính năng quan trọng cho phép bạn định nghĩa các giao diện ngầm (implicit interfaces) trong Python. Protocol giúp bạn tạo ra các hàm hoặc lớp linh hoạt hơn, có thể hoạt động với nhiều loại đối tượng khác nhau mà không cần quan tâm đến kiểu dữ liệu cụ thể, chỉ cần các đối tượng đó có các thuộc tính hoặc phương thức cần thiết. Qua việc sử dụng Protocol, bạn có thể xây dựng các chương trình dễ bảo trì và mở rộng hơn.

Giới thiệu về Python Protocol
Giả sử bạn có một hàm tính tổng giá trị của một danh sách sản phẩm, mỗi sản phẩm có các thuộc tính bao gồm tên, số lượng và giá:
from typing import List
class Product:
def __init__(self, name: str, quantity: float, price: float):
self.name = name
self.quantity = quantity
self.price = price
def calculate_total(items: List[Product]) -> float:
return sum([item.quantity * item.price for item in items])
Trong ví dụ này, hàm calculate_total() nhận vào một danh sách các đối tượng Product và trả về tổng giá trị.
Tuy nhiên, nếu bạn muốn hàm này linh hoạt hơn để có thể tính tổng giá trị cho các danh sách khác ngoài sản phẩm, bạn có thể sử dụng Protocol từ module typing trong Python.
Bài viết này được đăng tại [free tuts .net]
Sử dụng Python Protocol
Khi nhìn vào hàm calculate_total(), bạn có thể thấy rằng nó chỉ sử dụng hai thuộc tính là quantity (số lượng) và price (giá). Để làm cho hàm này linh hoạt hơn, ta có thể sử dụng Protocol để định nghĩa một giao diện cho các đối tượng có hai thuộc tính này mà không cần kế thừa từ một lớp cụ thể.
Protocol đã có sẵn từ Python 3.8, theo mô tả trong PEP 544.
Cách sử dụng Protocol
Đầu tiên, định nghĩa một lớp Item kế thừa từ Protocol, với hai thuộc tính là quantity và price:
class Item(Protocol):
quantity: float
price: float
Tiếp theo, sửa đổi hàm calculate_total() để nhận danh sách các đối tượng Item thay vì danh sách các đối tượng Product:
def calculate_total(items: List[Item]) -> float:
return sum([item.quantity * item.price for item in items])
Bằng cách này, bạn có thể truyền bất kỳ danh sách đối tượng nào có hai thuộc tính quantity và price vào hàm calculate_total().
Ví dụ hoàn chỉnh
from typing import List, Protocol
class Item(Protocol):
quantity: float
price: float
class Product:
def __init__(self, name: str, quantity: float, price: float):
self.name = name
self.quantity = quantity
self.price = price
def calculate_total(items: List[Item]) -> float:
return sum([item.quantity * item.price for item in items])
# Tính tổng danh sách sản phẩm
total = calculate_total([
Product('A', 10, 150),
Product('B', 5, 250)
])
print(total) # 2750
Áp dụng Protocol với các lớp khác
Bạn có thể định nghĩa một danh sách hàng tồn kho và truyền nó vào hàm calculate_total() như sau:
class Stock:
def __init__(self, product_name, quantity, price):
self.product_name = product_name
self.quantity = quantity
self.price = price
# Tính tổng danh sách hàng tồn kho
total = calculate_total([
Stock('Tablet', 5, 950),
Stock('Laptop', 10, 850)
])
print(total) # 13500
Trong ví dụ này, lớp Product và Stock không cần kế thừa từ Item, nhưng chúng vẫn có thể được sử dụng trong hàm calculate_total().
Duck Typing trong Python
Điều này được gọi là duck typing trong Python. Theo duck typing, hành vi và thuộc tính của đối tượng xác định loại của nó, thay vì kiểu tường minh của đối tượng. Nghĩa là, bất kỳ đối tượng nào có thuộc tính quantity và price đều tuân theo giao thức Item, bất kể kiểu tường minh của nó là gì.
Duck typing xuất phát từ nguyên tắc "kiểm tra con vịt":
Nếu nó đi như một con vịt và kêu như một con vịt, thì nó là một con vịt.
Trong thực tế, khi bạn viết một hàm chấp nhận dữ liệu đầu vào, điều quan trọng hơn là hành vi và thuộc tính của dữ liệu đầu vào chứ không phải kiểu cụ thể của nó.
Kết bài
Sử dụng Python Protocol giúp bạn định nghĩa các giao diện ngầm, tạo ra các hàm và lớp có tính linh hoạt cao mà vẫn đảm bảo đối tượng tuân thủ những yêu cầu về thuộc tính cần thiết. Điều này không chỉ giúp mã nguồn dễ bảo trì, mở rộng mà còn tối ưu hóa việc tái sử dụng, đặc biệt khi làm việc với nhiều loại đối tượng khác nhau mà không cần phụ thuộc vào kiểu dữ liệu cụ thể. Bằng cách tập trung vào các thuộc tính và hành vi của đối tượng, Python Protocol giúp cho việc phát triển phần mềm trở nên rõ ràng và hiệu quả hơn.

Các kiểu dữ liệu trong C ( int - float - double - char ...)
Thuật toán tìm ước chung lớn nhất trong C/C++
Cấu trúc lệnh switch case trong C++ (có bài tập thực hành)
ComboBox - ListBox trong lập trình C# winforms
Random trong Python: Tạo số random ngẫu nhiên
Lệnh cin và cout trong C++
Cách khai báo biến trong PHP, các loại biến thường gặp
Download và cài đặt Vertrigo Server
Thẻ li trong HTML
Thẻ article trong HTML5
Cấu trúc HTML5: Cách tạo template HTML5 đầu tiên
Cách dùng thẻ img trong HTML và các thuộc tính của img
Thẻ a trong HTML và các thuộc tính của thẻ a thường dùng