Hãy bắt đầu với các nhà trang trí Python.
Một bộ trang trí Python là một chức năng giúp thêm một số chức năng bổ sung vào một hàm đã được xác định.
Trong Python, mọi thứ đều là một đối tượng. Các chức năng trong Python là các đối tượng hạng nhất có nghĩa là chúng có thể được tham chiếu bởi một biến, được thêm vào trong danh sách, được truyền làm đối số cho một hàm khác, v.v.
Xem xét đoạn mã sau.
def decorator_func[fun]:
def wrapper_func[]:
print["Wrapper function started"]
fun[]
print["Given function decorated"]
# Wrapper function add something to the passed function and decorator
# returns the wrapper function
return wrapper_func
def say_bye[]:
print["bye!!"]
say_bye = decorator_func[say_bye]
say_bye[]
# Output:
# Wrapper function started
# bye!!
# Given function decorated
Ở đây, chúng ta có thể nói rằng chức năng trang trí đã sửa đổi chức năng Say_bye của chúng ta và thêm một số dòng mã bổ sung vào nó.
Cú pháp Python cho người trang trí
def decorator_func[fun]:
def wrapper_func[]:
print["Wrapper function started"]
fun[]
print["Given function decorated"]
# Wrapper function add something to the passed function and decorator
# returns the wrapper function
return wrapper_func
@decorator_func
def say_bye[]:
print["bye!!"]
say_bye[]
Chúng ta hãy trải qua mọi thứ với một kịch bản trường hợp. Nhưng trước đó, chúng ta hãy nói về một số nguyên tắc OOP.
Getters và setters được sử dụng trong nhiều ngôn ngữ lập trình hướng đối tượng để đảm bảo nguyên tắc đóng gói dữ liệu [được coi là gói dữ liệu với các phương thức hoạt động trên các dữ liệu này.]
Tất nhiên, các phương pháp này là getter để truy xuất dữ liệu và setter để thay đổi dữ liệu.
Theo nguyên tắc này, các thuộc tính của một lớp được làm riêng để ẩn và bảo vệ chúng khỏi mã khác.
Yup, @Property về cơ bản là một cách pythonic để sử dụng getters và setters.@property is basically a pythonic way to use getters and setters.
Python có một khái niệm tuyệt vời gọi là thuộc tính làm cho cuộc sống của một lập trình viên hướng đối tượng đơn giản hơn nhiều.
Chúng ta hãy giả sử rằng bạn quyết định tạo ra một lớp có thể lưu trữ nhiệt độ theo độ C.
class Celsius:
def __init__[self, temperature = 0]:
self.set_temperature[temperature]
def to_fahrenheit[self]:
return [self.get_temperature[] * 1.8] + 32
def get_temperature[self]:
return self._temperature
def set_temperature[self, value]:
if value < -273:
raise ValueError["Temperature below -273 is not possible"]
self._temperature = value
Mã được tái cấu trúc, đây là cách chúng ta có thể đạt được nó với 'tài sản'.
Trong Python, Property [] là một hàm tích hợp 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, getter [], setter [] và delete [].
class Celsius:
def __init__[self, temperature = 0]:
self.temperature = temperature
def to_fahrenheit[self]:
return [self.temperature * 1.8] + 32
def get_temperature[self]:
print["Getting value"]
return self.temperature
def set_temperature[self, value]:
if value < -273:
raise ValueError["Temperature below -273 is not possible"]
print["Setting value"]
self.temperature = value
temperature = property[get_temperature,set_temperature]
Here,
temperature = property[get_temperature,set_temperature]
có thể đã bị phá vỡ như,
# make empty property
temperature = property[]
# assign fget
temperature = temperature.getter[get_temperature]
# assign fset
temperature = temperature.setter[set_temperature]
Chỉ cần lưu ý:
- get_temate vẫn là một thuộc tính thay vì một phương thức.
Bây giờ bạn có thể truy cập giá trị của nhiệt độ bằng cách viết.
C = Celsius[]
C.temperature
# instead of writing C.get_temperature[]
Chúng ta có thể tiếp tục xa hơn và không xác định tên get_temate và set_temate vì chúng không cần thiết và gây ô nhiễm không gian tên lớp.
Cách pythonic để giải quyết vấn đề trên là sử dụng @property.pythonic way to deal with the above problem is to use @property.
class Celsius:
def __init__[self, temperature = 0]:
self.temperature = temperature
def to_fahrenheit[self]:
return [self.temperature * 1.8] + 32
@property
def temperature[self]:
print["Getting value"]
return self.temperature
@temperature.setter
def temperature[self, value]:
if value < -273:
raise ValueError["Temperature below -273 is not possible"]
print["Setting value"]
self.temperature = value
Điểm cần lưu ý -
- Một phương pháp được sử dụng để nhận được giá trị được trang trí bằng "@property".
- Phương pháp phải hoạt động như setter được trang trí bằng "@nhiệt độ.setter", nếu hàm được gọi là "x", chúng ta sẽ phải trang trí nó bằng "@x.setter".
- Chúng tôi đã viết "hai" các phương thức có cùng tên và một số lượng tham số khác nhau, "nhiệt độ def [tự]" và "nhiệt độ def [self, x]".
Như bạn có thể thấy, mã chắc chắn ít thanh lịch hơn.
Bây giờ, chúng ta hãy nói về một kịch bản thực tế ngoài đời thực.
Giả sử bạn đã thiết kế một lớp như sau:
class OurClass:
def __init__[self, a]:
self.x = a
y = OurClass[10]
print[y.x]
Bây giờ, hãy giả sử rằng lớp học của chúng tôi đã phổ biến trong các khách hàng và họ bắt đầu sử dụng nó trong các chương trình của họ, họ đã thực hiện tất cả các loại bài tập cho đối tượng.
Và một ngày định mệnh, một khách hàng đáng tin cậy đã đến với chúng tôi và cho rằng "x" phải là một giá trị từ 0 đến 1000; Đây thực sự là một kịch bản khủng khiếp!
Do thuộc tính, thật dễ dàng: Chúng tôi tạo phiên bản thuộc tính của "X".
class OurClass:
def __init__[self,x]:
self.x = x
@property
def x[self]:
return self.__x
@x.setter
def x[self, x]:
if x < 0:
self.__x = 0
elif x > 1000:
self.__x = 1000
else:
self.__x = x
Điều này thật tuyệt, không phải là nó: Bạn có thể bắt đầu với việc triển khai đơn giản nhất có thể tưởng tượng được và bạn có thể tự do chuyển sang phiên bản thuộc tính mà không phải thay đổi giao diện! Vì vậy, các thuộc tính không chỉ là một sự thay thế cho getters và setters!
Bạn có thể kiểm tra triển khai này ở đây