Chào mừng! Trong bài viết này, bạn sẽ học cách làm việc với người trang trí 🔹 Gặp gỡ tài sản
7 trong Python.def decorator[f]:
def new_function[]:
print["Extra Functionality"]
f[]
return new_function
Bạn sẽ học:
- Những lợi thế của việc làm việc với các tài sản trong Python.
- Những điều cơ bản của các chức năng trang trí: chúng là gì và cách chúng liên quan đến @property.
- Cách bạn có thể sử dụng @Property để xác định getters, setters và deleter.
1⃣ Ưu điểm của các tài sản trong Python
Hãy bắt đầu với một chút bối cảnh. Tại sao bạn sẽ sử dụng các thuộc tính trong Python?Why would you use properties in Python?
Các thuộc tính có thể được coi là cách làm việc "Pythonic" với các thuộc tính vì:
- Cú pháp được sử dụng để xác định các thuộc tính là rất ngắn gọn và có thể đọc được.
- Bạn có thể truy cập các thuộc tính thể hiện chính xác như thể chúng là thuộc tính công khai trong khi sử dụng "ma thuật" của các trung gian [getters và setters] để xác thực các giá trị mới và để tránh truy cập hoặc sửa đổi trực tiếp dữ liệu.
- Bằng cách sử dụng @Property, bạn có thể "tái sử dụng" tên của một thuộc tính để tránh tạo tên mới cho Getters, Setters và Deleter.
Những lợi thế này làm cho các thuộc tính trở thành một công cụ thực sự tuyệt vời để giúp bạn viết mã ngắn gọn và dễ đọc hơn. ??
2⃣ Giới thiệu về trang tríDecorators
Một hàm trang trí về cơ bản là một chức năng thêm chức năng mới cho một hàm được truyền làm đối số. Sử dụng một chức năng trang trí giống như thêm rắc sô cô la vào một loại kem?. Nó cho phép chúng tôi thêm chức năng mới vào một chức năng hiện có mà không cần sửa đổi nó.decorator function is basically a function that adds new functionality to a function that is passed as argument. Using a decorator function is like adding chocolate sprinkles to an ice cream ?. It lets us add new functionality to an existing function without modifying it.
Trong ví dụ dưới đây, bạn có thể thấy chức năng trang trí điển hình trông như thế nào trong Python:
def decorator[f]:
def new_function[]:
print["Extra Functionality"]
f[]
return new_function
@decorator
def initial_function[]:
print["Initial Functionality"]
initial_function[]
Hãy phân tích các yếu tố này một cách chi tiết:
- Trước tiên chúng tôi tìm thấy hàm trang trí
8 [rắc ✨] có hàmdef decorator[f]: def new_function[]: print["Extra Functionality"] f[] return new_function
9 làm đối số.def decorator[f]: def new_function[]: print["Extra Functionality"] f[] return new_function
def decorator[f]:
def new_function[]:
print["Extra Functionality"]
f[]
return new_function
- Chức năng trang trí này có chức năng lồng nhau,
0. Lưu ý cách@decorator def initial_function[]: print["Initial Functionality"] initial_function[]
9 được gọi bên trongdef decorator[f]: def new_function[]: print["Extra Functionality"] f[] return new_function
0 để đạt được chức năng tương tự trong khi thêm chức năng mới trước khi gọi chức năng [chúng tôi cũng có thể thêm chức năng mới sau khi gọi chức năng].@decorator def initial_function[]: print["Initial Functionality"] initial_function[]
- Chức năng trang trí tự trả về chức năng lồng nhau
0.@decorator def initial_function[]: print["Initial Functionality"] initial_function[]
- Sau đó [bên dưới], chúng tôi tìm thấy chức năng sẽ được trang trí [kem?]
4. Lưu ý cú pháp rất đặc biệt [@decorator def initial_function[]: print["Initial Functionality"] initial_function[]
5] trên tiêu đề chức năng.@decorator def initial_function[]: print["Initial Functionality"] initial_function[]
@decorator
def initial_function[]:
print["Initial Functionality"]
initial_function[]
Nếu chúng ta chạy mã, chúng ta sẽ thấy đầu ra này:
Extra Functionality
Initial Functionality
Lưu ý cách chức năng trang trí chạy ngay cả khi chúng ta chỉ gọi
@decorator
def initial_function[]:
print["Initial Functionality"]
initial_function[]
6. Đây là phép thuật của việc thêm @Decorator?.💡note: Nói chung, chúng tôi sẽ viết
7, thay thế tên của hàm trang trí sau ký hiệu @. In general, we would write @decorator
def initial_function[]:
print["Initial Functionality"]
initial_function[]
@decorator
def initial_function[]:
print["Initial Functionality"]
initial_function[]
7, replacing the name of the decorator function after the @ symbol.Tôi biết bạn có thể hỏi: Điều này liên quan đến @property như thế nào? @Property là một công cụ trang trí tích hợp cho hàm tài sản [] trong Python. Nó được sử dụng để cung cấp chức năng "đặc biệt" cho một số phương pháp nhất định để làm cho chúng hoạt động như getters, setters hoặc deleter khi chúng ta xác định các thuộc tính trong một lớp. The @property is a built-in decorator for the property[] function in Python. It is used to give "special" functionality to certain methods to make them act as getters, setters, or deleters when we define properties in a class.
Bây giờ bạn đã quen thuộc với các nhà trang trí, hãy xem một kịch bản thực sự về việc sử dụng @Property!
Kịch bản trong thế giới thực: @Property
Hãy nói rằng lớp này là một phần của chương trình của bạn. Bạn đang mô hình hóa một ngôi nhà với lớp
@decorator
def initial_function[]:
print["Initial Functionality"]
initial_function[]
8 [hiện tại, lớp chỉ có thuộc tính phiên bản giá được xác định]:class House:
def __init__[self, price]:
self.price = price
Thuộc tính trường hợp này là công khai vì tên của nó không có dấu gạch dưới hàng đầu. Vì thuộc tính hiện đang được công khai, rất có khả năng bạn và các nhà phát triển khác trong nhóm của bạn đã truy cập và sửa đổi thuộc tính trực tiếp trong các phần khác của chương trình bằng cách sử dụng ký hiệu DOT, như thế này:directly in other parts of the program using dot notation, like this:
# Access value
obj.price
# Modify value
obj.price = 40000
Mẹo: OBJ đại diện cho một biến tham chiếu một ví dụ là
@decorator
def initial_function[]:
print["Initial Functionality"]
initial_function[]
8.Tip: obj represents a variable that references an instance of @decorator
def initial_function[]:
print["Initial Functionality"]
initial_function[]
8. Cho đến nay mọi thứ đang hoạt động rất tốt, phải không? Butlet nói rằng bạn được yêu cầu làm cho thuộc tính này được bảo vệ [không công khai] và xác nhận giá trị mới trước khi gán nó. Cụ thể, bạn cần kiểm tra xem giá trị có phải là phao dương không. Bạn làm điều đó như thế nào? Hãy xem nào.But let's say that you are asked to make this attribute protected [non-public] and validate the new value before assigning it. Specifically, you need to check if the value is a positive float. How would you do that? Let's see.
Thay đổi mã của bạn
Tại thời điểm này, nếu bạn quyết định thêm getters và setters, bạn và nhóm của bạn có thể sẽ hoảng loạn?. Điều này là do mỗi dòng mã truy cập hoặc sửa đổi giá trị của thuộc tính sẽ phải được sửa đổi để gọi getter hoặc setter, tương ứng. Nếu không, mã sẽ bị phá vỡ.
# Changed from obj.price
obj.get_price[]
# Changed from obj.price = 40000
obj.set_price[40000]
Nhưng ... tài sản đến giải cứu! Với
7, bạn và nhóm của bạn sẽ không cần sửa đổi bất kỳ dòng nào trong số đó vì bạn có thể thêm getters và setters "phía sau hậu trường" mà không ảnh hưởng đến cú pháp mà bạn đã sử dụng để truy cập hoặc sửa đổi thuộc tính khi nó được công khai. With def decorator[f]:
def new_function[]:
print["Extra Functionality"]
f[]
return new_function
def decorator[f]:
def new_function[]:
print["Extra Functionality"]
f[]
return new_function
7, you and your team will not need to modify any of those lines because you will able to add getters and setters "behind the scenes" without affecting the syntax that you used to access or modify the attribute when it was public. Tuyệt vời, phải không? & nbsp;
Nếu bạn quyết định sử dụng
def decorator[f]:
def new_function[]:
print["Extra Functionality"]
f[]
return new_function
7, lớp của bạn sẽ trông giống như ví dụ dưới đây:class House:
def __init__[self, price]:
self._price = price
@property
def price[self]:
return self._price
@price.setter
def price[self, new_price]:
if new_price > 0 and isinstance[new_price, float]:
self._price = new_price
else:
print["Please enter a valid price"]
@price.deleter
def price[self]:
del self._price
Cụ thể, bạn có thể xác định ba phương thức cho một thuộc tính:three methods for a property:
- Một getter - để truy cập giá trị của thuộc tính.getter - to access the value of the attribute.
- Một setter - để đặt giá trị của thuộc tính.setter - to set the value of the attribute.
- Một DELETER - Để xóa thuộc tính phiên bản.deleter - to delete the instance attribute.
Giá bây giờ là "được bảo vệ", xin lưu ý rằng thuộc tính giá hiện được coi là "được bảo vệ" vì chúng tôi đã thêm một dấu gạch dưới hàng đầu vào tên của nó trong
2:Extra Functionality
Initial Functionality
Please note that the price attribute is now considered "protected" because we added a leading underscore to its name in
Extra Functionality
Initial Functionality
2:self._price = price
Trong Python, theo quy ước, khi bạn thêm một dấu gạch dưới hàng đầu vào một tên, bạn đang nói với các nhà phát triển khác rằng nó không nên được truy cập hoặc sửa đổi trực tiếp bên ngoài lớp. Nó chỉ nên được truy cập thông qua các trung gian [getters và setters] nếu chúng có sẵn.
🔸 getter
Ở đây chúng tôi có phương pháp getter:
@property
def price[self]:
return self._price
Lưu ý cú pháp:
7 - Được sử dụng để chỉ ra rằng chúng ta sẽ xác định một thuộc tính. Lưu ý làm thế nào điều này ngay lập tức cải thiện khả năng đọc vì chúng ta có thể thấy rõ mục đích của phương pháp này.def decorator[f]: def new_function[]: print["Extra Functionality"] f[] return new_function
4 - Tiêu đề. Lưu ý cách getter được đặt tên chính xác giống như tài sản mà chúng tôi đang xác định: Giá. Đây là tên mà chúng tôi sẽ sử dụng để truy cập và sửa đổi thuộc tính bên ngoài lớp. Phương thức chỉ lấy một tham số chính thức, tự, là một tham chiếu đến thể hiện.Extra Functionality Initial Functionality
5 - Dòng này chính xác là những gì bạn mong đợi trong một getter thường xuyên. Giá trị của thuộc tính được bảo vệ được trả về.Extra Functionality Initial Functionality
Dưới đây là một ví dụ về việc sử dụng phương pháp Getter:
def decorator[f]:
def new_function[]:
print["Extra Functionality"]
f[]
return new_function
0Lưu ý cách chúng tôi truy cập thuộc tính giá như thể nó là một thuộc tính công khai. Chúng tôi hoàn toàn không thay đổi cú pháp, nhưng chúng tôi thực sự đang sử dụng getter làm trung gian để tránh truy cập trực tiếp vào dữ liệu.
Setter
Bây giờ chúng tôi có phương thức setter:
def decorator[f]:
def new_function[]:
print["Extra Functionality"]
f[]
return new_function
1Lưu ý cú pháp:
7 - Được sử dụng để chỉ ra rằng chúng ta sẽ xác định một thuộc tính. Lưu ý làm thế nào điều này ngay lập tức cải thiện khả năng đọc vì chúng ta có thể thấy rõ mục đích của phương pháp này.not using @property.setter, we are using @price.setter. The name of the property is included before .setter.def decorator[f]: def new_function[]: print["Extra Functionality"] f[] return new_function
4 - Tiêu đề. Lưu ý cách getter được đặt tên chính xác giống như tài sản mà chúng tôi đang xác định: Giá. Đây là tên mà chúng tôi sẽ sử dụng để truy cập và sửa đổi thuộc tính bên ngoài lớp. Phương thức chỉ lấy một tham số chính thức, tự, là một tham chiếu đến thể hiện.Extra Functionality Initial Functionality
5 - Dòng này chính xác là những gì bạn mong đợi trong một getter thường xuyên. Giá trị của thuộc tính được bảo vệ được trả về.validate the argument to check if it is a positive float and then, if the argument is valid, we update the value of the attribute. If the value is not valid, a descriptive message is printed. You can choose how to handle invalid values according the needs of your program.Extra Functionality Initial Functionality
Dưới đây là một ví dụ về việc sử dụng phương pháp Getter:
def decorator[f]:
def new_function[]:
print["Extra Functionality"]
f[]
return new_function
2Lưu ý cách chúng tôi truy cập thuộc tính giá như thể nó là một thuộc tính công khai. Chúng tôi hoàn toàn không thay đổi cú pháp, nhưng chúng tôi thực sự đang sử dụng getter làm trung gian để tránh truy cập trực tiếp vào dữ liệu.
def decorator[f]:
def new_function[]:
print["Extra Functionality"]
f[]
return new_function
3Setter
def decorator[f]:
def new_function[]:
print["Extra Functionality"]
f[]
return new_function
4Bây giờ chúng tôi có phương thức setter:Tip: This proves that the setter method is working as an intermediary. It is being called "behind the scenes" when we try to update the value, so the descriptive message is displayed when the value is not valid.
Extra Functionality
Initial Functionality
6 - Được sử dụng để chỉ ra rằng đây là phương thức setter cho tài sản giá. Lưu ý rằng chúng tôi không sử dụng @property.setter, chúng tôi đang sử dụng @price.setter. Tên của tài sản được bao gồm trước .Setter.
Extra Functionality
Initial Functionality
Extra Functionality
Initial Functionality
7 - Tiêu đề và danh sách các tham số. Lưu ý cách tên của thuộc tính được sử dụng làm tên của setter. Chúng tôi cũng có một tham số chính thức thứ hai [new_price], là giá trị mới sẽ được gán cho thuộc tính giá [nếu nó hợp lệ].def decorator[f]:
def new_function[]:
print["Extra Functionality"]
f[]
return new_function
5Lưu ý cú pháp:
7 - Được sử dụng để chỉ ra rằng chúng ta sẽ xác định một thuộc tính. Lưu ý làm thế nào điều này ngay lập tức cải thiện khả năng đọc vì chúng ta có thể thấy rõ mục đích của phương pháp này.deleter.def decorator[f]: def new_function[]: print["Extra Functionality"] f[] return new_function
4 - Tiêu đề. Lưu ý cách getter được đặt tên chính xác giống như tài sản mà chúng tôi đang xác định: Giá. Đây là tên mà chúng tôi sẽ sử dụng để truy cập và sửa đổi thuộc tính bên ngoài lớp. Phương thức chỉ lấy một tham số chính thức, tự, là một tham chiếu đến thể hiện.Extra Functionality Initial Functionality
5 - Dòng này chính xác là những gì bạn mong đợi trong một getter thường xuyên. Giá trị của thuộc tính được bảo vệ được trả về.Extra Functionality Initial Functionality
Dưới đây là một ví dụ về việc sử dụng phương pháp Getter:Tip: Notice that the name of the property is "reused" for all three methods.
Lưu ý cách chúng tôi truy cập thuộc tính giá như thể nó là một thuộc tính công khai. Chúng tôi hoàn toàn không thay đổi cú pháp, nhưng chúng tôi thực sự đang sử dụng getter làm trung gian để tránh truy cập trực tiếp vào dữ liệu.
def decorator[f]:
def new_function[]:
print["Extra Functionality"]
f[]
return new_function
6Setter
Bây giờ chúng tôi có phương thức setter:
Extra Functionality
Initial Functionality
6 - Được sử dụng để chỉ ra rằng đây là phương thức setter cho tài sản giá. Lưu ý rằng chúng tôi không sử dụng @property.setter, chúng tôi đang sử dụng @price.setter. Tên của tài sản được bao gồm trước .Setter.Extra Functionality
Initial Functionality
7 - Tiêu đề và danh sách các tham số. Lưu ý cách tên của thuộc tính được sử dụng làm tên của setter. Chúng tôi cũng có một tham số chính thức thứ hai [new_price], là giá trị mới sẽ được gán cho thuộc tính giá [nếu nó hợp lệ].Cuối cùng, chúng tôi có thân máy của bộ setter nơi chúng tôi xác nhận đối số để kiểm tra xem đó có phải là một float tích cực và sau đó, nếu đối số là hợp lệ, chúng tôi cập nhật giá trị của thuộc tính. Nếu giá trị không hợp lệ, một thông báo mô tả được in. Bạn có thể chọn cách xử lý các giá trị không hợp lệ theo nhu cầu của chương trình của bạn.
Đây là một ví dụ về việc sử dụng phương thức setter với @property:
- Lưu ý cách chúng tôi không thay đổi cú pháp, nhưng bây giờ chúng tôi đang sử dụng một trung gian [setter] để xác thực đối số trước khi gán nó. Giá trị mới [45000.0] được truyền như một đối số cho người đặt:
- Nếu chúng tôi cố gắng gán một giá trị không hợp lệ, chúng tôi sẽ thấy thông báo mô tả. Chúng tôi cũng có thể kiểm tra xem giá trị không được cập nhật:
- Mẹo: Điều này chứng minh rằng phương pháp setter đang hoạt động như một trung gian. Nó đang được gọi là "Phía sau hậu trường" khi chúng tôi cố gắng cập nhật giá trị, vì vậy thông báo mô tả được hiển thị khi giá trị không hợp lệ.
Tôi thực sự hy vọng bạn thích bài viết của tôi và thấy nó hữu ích. Để tìm hiểu thêm về các thuộc tính và lập trình theo định hướng đối tượng trong Python, hãy xem khóa học trực tuyến của tôi, bao gồm hơn 6 giờ bài giảng video, bài tập mã hóa và các dự án nhỏ. To learn more about Properties and Object Oriented Programming in Python, check out my online course, which includes 6+ hours of video lectures, coding exercises, and mini projects.
Học mã miễn phí. Chương trình giảng dạy nguồn mở của Freecodecamp đã giúp hơn 40.000 người có được việc làm với tư cách là nhà phát triển. Bắt đầu