Python: Getter và Setter
Getter và Setter trong Python không giống như những ngôn ngữ lập trình hướng đối tượng khác. Về cơ bản, mục đích chính của việc sử dụng Getter và Setter trong các chương trình hướng đối tượng là để đảm bảo tính đóng gói dữ liệu. Các biến private trong python thực sự không phải là trường ẩn như trong các ngôn ngữ hướng đối tượng khác. Getter và Setter trong python thường được sử dụng khi:
- Thêm logic xác thực khi thực hiện nhận (get) và đặt (set) giá trị.
- Để tránh truy cập trực tiếp vào thuộc tính của lớp.
Sử dụng hàm bình thường để đạt được hành vi Getter và Setter
Nếu ta định nghĩa các phương thức get()
và set()
một cách bình thường thì nó sẽ không phản ánh bất kỳ triển khai đặc biệt nào cả.
Ví dụ:
import self as self class Student: def __init__(self, age=0): self._age = age # phương thức getter def get_age(self): return self._age # phương thức setter def set_age(self, x): self._age = x stu = Student() # thiết lập tuổi sử dụng setter stu.set_age(21) # truy xuất tuổi sử dụng getter print(stu.get_age()) print(stu._age)
Kết quả:
21
21
Trong đoạn code ở trên thì get_age()
và set_age()
hoạt động như các hàm bình thường và không mang ý nghĩa nhiều lắm của Getter cũng như Setter. Để làm được điều này, Python có một hàm đặc biệt là property()
.
Sử dụng hàm property() để đạt được hành vi của Getter và Setter
property()
là một hàm có sẵn, nó tạo và trả về một đối tượng thuộc tính. Một đối tượng thuộc tính có ba phương thức là getter()
, setter()
và delete()
. Hàm property()
có bốn đối số là property(fget, fset, fdel, doc)
, trong đó fget
là hàm để truy xuất giá trị của thuộc tính, fset
là hàm để thiết lập giá trị cho thuộc tính, fdel
là hàm để xóa giá trị thuộc tính, doc
sẽtạo một chuỗi doc cho thuộc tính. Ba phương thức, getter()
, setter()
và delete()
sẽ chỉ định fget
, fset
và fdel
tương ứng.
Ví dụ:
class Student: def __init__(self): self._age = 0 # hàm để lấy giá trị của _age def get_age(self): print("phương thức getter được gọi!") return self._age # hàm để thiết lập giá trị cho _age def set_age(self, a): print("phương thức setter được gọi!") self._age = a # hàm để xóa thuộc tính _age def del_age(self): print("_a sẽ bị xóa!") del self._age age = property(get_age, set_age, del_age) stu = Student() stu.age = 10 # kích hoạt setter print(stu.age) # kích hoạt getter del stu.age # kích hoạt deleter
Kết quả:
phương thức setter được gọi!
phương thức getter được gọi!
10
_a sẽ bị xóa!
Trong đoạn code trên thì age
chính là đối tượng thuộc tính và nó sẽ giữ an toàn cho thuộc tính _age.
Sử dụng decorator @property để đạt được hành vi Getter và Setter
Có một cách nữa để đạt được hành vi Getter và Setter là bằng cách sử dụng decorator @property. Mục đích chính của bất kỳ decorator nào là thay đổi các phương thức hoặc thuộc tính lớp của bạn theo cách sao cho người dùng lớp của bạn không cần thực hiện bất kỳ thay đổi nào trong code của họ.
Ví dụ:
class Student: def __init__(self): self._age = 0 @property # decorate phương thức getter def age(self): print("getter method called") return self._age @age.setter # decorate phương thức setter def age(self, a): if a < 18: raise ValueError("Sorry you age is below eligibility criteria") print("setter method called") self._age = a @age.deleter # decorate phương thức deleter def age(self): print("Xóa thuộc tính _age!") del self._age stu = Student() stu.age = 19 # gọi setter print(stu.age) # gọi getter del stu.age # gọi deleter
Kết quả:
setter method called
getter method called
19
Xóa thuộc tính _age!
Trong đoạn code trên, rõ ràng rằng cách sử dụng decorator @property
để tạo Getter và Setter theo cách pythonic. Line 15-16
hoạt động như một mã xác thực tăng a ValueError
nếu chúng ta cố gắng khởi tạo tuổi với giá trị nhỏ hơn 18, Bằng cách này, bất kỳ loại xác thực nào cũng có thể được áp dụng trong các hàm getter hoặc setter.