Chức năng bọc python

Bạn đã từng gặp loại cú pháp đặc biệt

def hello[name]:
    "đây là một hàm bình thường"
    print[f'Hello, {name}. Welcome to heaven!']
def welcome[]:
    "đây là một hàm bậc cao, kết quả trả về là một hàm khác"
    return hello
# lời gọi hàm welcome[] sẽ tạo ra một hàm mới xxx tương đương với hàm hello[]
xxx = welcome[]
# xxx có thể xem như là một tên gọi khác của hello[]
xxx['Obama']
3,
def hello[name]:
    "đây là một hàm bình thường"
    print[f'Hello, {name}. Welcome to heaven!']
def welcome[]:
    "đây là một hàm bậc cao, kết quả trả về là một hàm khác"
    return hello
# lời gọi hàm welcome[] sẽ tạo ra một hàm mới xxx tương đương với hàm hello[]
xxx = welcome[]
# xxx có thể xem như là một tên gọi khác của hello[]
xxx['Obama']
4,
def hello[name]:
    "đây là một hàm bình thường"
    print[f'Hello, {name}. Welcome to heaven!']
def welcome[]:
    "đây là một hàm bậc cao, kết quả trả về là một hàm khác"
    return hello
# lời gọi hàm welcome[] sẽ tạo ra một hàm mới xxx tương đương với hàm hello[]
xxx = welcome[]
# xxx có thể xem như là một tên gọi khác của hello[]
xxx['Obama']
5khi xây dựng lớp học. Trong Python, cú pháp ngược này là một cách sử dụng của decorator. Trình trang trí là một hàm nhận hàm khác làm tham số để mở rộng khả năng của tham số hàm [nhưng không cần điều chỉnh thân hàm tham số]. Bài học này sẽ trình bày chi tiết các vấn đề liên quan đến việc xây dựng và sử dụng trình trang trí trong Python

ĐỘI DUNG CỦA BẢN DỊCH Ẩn

1. Decorator là gì?

2. Hàm bậc cao

3. Hàm lồng nhau và đóng

4. Xây dựng trình trang trí hàm trong Python

5. Một số vấn đề khác với người trang trí

6. Kết luận

Decorator là gì?

Trình trang trí là một mẫu thiết kế [mẫu thiết kế] cho phép điều chỉnh chức năng mở rộng của một đối tượng mà không cần thiết có thể điều chỉnh mã của nó. Đây là một số trong các mẫu thiết kế cổ điển

Trong Python mẫu thiết bị trang trí được hỗ trợ và sử dụng rộng rãi

Khi học về phương thức [method] và thuộc tính [property] trong lớp Python, bạn đã gặp một số cách viết lạ như

def hello[name]:
    "đây là một hàm bình thường"
    print[f'Hello, {name}. Welcome to heaven!']
def welcome[]:
    "đây là một hàm bậc cao, kết quả trả về là một hàm khác"
    return hello
# lời gọi hàm welcome[] sẽ tạo ra một hàm mới xxx tương đương với hàm hello[]
xxx = welcome[]
# xxx có thể xem như là một tên gọi khác của hello[]
xxx['Obama']
3,
def hello[name]:
    "đây là một hàm bình thường"
    print[f'Hello, {name}. Welcome to heaven!']
def welcome[]:
    "đây là một hàm bậc cao, kết quả trả về là một hàm khác"
    return hello
# lời gọi hàm welcome[] sẽ tạo ra một hàm mới xxx tương đương với hàm hello[]
xxx = welcome[]
# xxx có thể xem như là một tên gọi khác của hello[]
xxx['Obama']
4,
def hello[name]:
    "đây là một hàm bình thường"
    print[f'Hello, {name}. Welcome to heaven!']
def welcome[]:
    "đây là một hàm bậc cao, kết quả trả về là một hàm khác"
    return hello
# lời gọi hàm welcome[] sẽ tạo ra một hàm mới xxx tương đương với hàm hello[]
xxx = welcome[]
# xxx có thể xem như là một tên gọi khác của hello[]
xxx['Obama']
5. Họ được gọi là những người trang trí [hàm trang trí]

Trình trang trí trong Python là các hàm nhận hàm khác làm tham số để mở rộng khả năng của hàm tham số [nhưng không cần điều chỉnh thân hàm tham số]

Hàm trang trí trong Python chính là một vận dụng của mẫu thiết kế trang trí

Vì sao lại cần trang trí trong Python?

Trong quá trình xây dựng hàm, bạn có thể gặp các yêu cầu chung khi lặp lại vòng lặp. Lấy ví dụ, trong một số trường hợp bạn sẽ muốn ghi chú [log] lại quá trình thực hiện của một hàm để theo dõi và gỡ lỗi. You could have to start a số tài nguyên trước khi chức năng có thể hoạt động. Bạn có thể muốn hủy đối tượng Dẹp sau khi một hàm kết thúc. Bạn có thể muốn đo thời gian thực hiện của một hàm bằng cách tính khoảng thời gian từ lúc bắt đầu đến lúc kết thúc thực hiện hàm

Tất nhiên, bạn có thể viết tất cả các logic trên trong hàm. Tuy nhiên, hãy nghĩ đến vấn đề giải quyết của bạn có rất nhiều chức năng phải xử lý tương tự nhau. Liệu bạn có muốn sao chép đoạn mã tới tất cả các hàm cần xử lý?

Khi đó, decorator sẽ giúp bạn bổ sung các tính năng cần thiết vào một hàm mà không cần viết thêm code cho hàm đó. Bạn có thể giữ nguyên hàm với các tính năng cơ bản của nó

Về kỹ thuật, decorator trong Python thực chất là một hàm nhận một hàm khác làm tham số và trả lại kết quả cũng là một hàm. Python has a number of supports giúp đơn giản hóa công việc sử dụng hàm trang trí

Các vấn đề như “hàm làm tham số” và “hàm làm kết quả” có thể hơi khó hiểu. Chúng ta sẽ thích giải thích từng vấn đề qua các phần tiếp theo

high level

Trong Python, bạn có thể truyền một hàm làm tham số của một hàm khác

Lưu ý. truyền hàm làm tham số không giống như truyền lời gọi hàm. Khi truyền hàm làm tham số, bạn chỉ truyền tên hàm. Trong thân hàm chính có thể gọi hàm tham số như một hàm thông thường

Vui lòng xem ví dụ sau đây

def hello[name]:
    print[f'Hello, {name}. Welcome to heaven!']
def hi[name]:
    print[f'Hi, {name}. Welcome to hell!']
def greeting[name, func]:
    print['Inside high order function:']
    func[name]
    print['---']
greeting['Donald Trump', hello]
greeting['Vladimir Putin', hi]

Trong ví dụ trên, hi và hello là hai hàm bình thường. Các chức năng này nhận một chuỗi tên người và trong lời chào

Trong khi đó,

def hello[name]:
    "đây là một hàm bình thường"
    print[f'Hello, {name}. Welcome to heaven!']
def welcome[]:
    "đây là một hàm bậc cao, kết quả trả về là một hàm khác"
    return hello
# lời gọi hàm welcome[] sẽ tạo ra một hàm mới xxx tương đương với hàm hello[]
xxx = welcome[]
# xxx có thể xem như là một tên gọi khác của hello[]
xxx['Obama']
9 lại là một hàm bậc cao. nó nhận hai tham số [
def welcome[greeting: 'lời chào']:
    def hello[name: 'tên người']:
        print[f'{greeting}, {name}. Welcome to heaven!']
    return hello
hi = welcome['Hello']
hi['Putin']
0 và
def welcome[greeting: 'lời chào']:
    def hello[name: 'tên người']:
        print[f'{greeting}, {name}. Welcome to heaven!']
    return hello
hi = welcome['Hello']
hi['Putin']
1]. Qua hình thức tiêu đề, hello[] không khác gì so với hi[] hay hello[]. Tuy nhiên, khi nhìn vào hàm thân, bạn phải đặt câu lệnh cho dòng lệnh
def welcome[greeting: 'lời chào']:
    def hello[name: 'tên người']:
        print[f'{greeting}, {name}. Welcome to heaven!']
    return hello
hi = welcome['Hello']
hi['Putin']
2. Đây là lời gọi hàm chứ không phải là lệnh truy xuất giá trị

Như vậy, tham số

def welcome[greeting: 'lời chào']:
    def hello[name: 'tên người']:
        print[f'{greeting}, {name}. Welcome to heaven!']
    return hello
hi = welcome['Hello']
hi['Putin']
1 của
def hello[name]:
    "đây là một hàm bình thường"
    print[f'Hello, {name}. Welcome to heaven!']
def welcome[]:
    "đây là một hàm bậc cao, kết quả trả về là một hàm khác"
    return hello
# lời gọi hàm welcome[] sẽ tạo ra một hàm mới xxx tương đương với hàm hello[]
xxx = welcome[]
# xxx có thể xem như là một tên gọi khác của hello[]
xxx['Obama']
9 không phải là một giá trị mà là một hàm. Hàm tham số này có thể được sử dụng bình thường bên trong thân hàm chính

Một hàm nhận một hàm khác làm tham số được gọi là hàm bậc cao

Hàm lồng nhau và đóng

Trong Python, một hàm có thể trả kết quả là một hàm khác. Trả lại một hàm làm kết quả có nghĩa là bạn có thể gọi hàm kết quả đó là một hàm khai báo theo kiểu bình thường thông thường

Please view ví dụ sau

def hello[name]:
    "đây là một hàm bình thường"
    print[f'Hello, {name}. Welcome to heaven!']
def welcome[]:
    "đây là một hàm bậc cao, kết quả trả về là một hàm khác"
    return hello
# lời gọi hàm welcome[] sẽ tạo ra một hàm mới xxx tương đương với hàm hello[]
xxx = welcome[]
# xxx có thể xem như là một tên gọi khác của hello[]
xxx['Obama']

Trong ví dụ này, hello[] là một hàm thông thường trong lời chào

Tuy nhiên, welcome[] lại là một hàm đặc biệt. kết quả trả về của nó không phải là một giá trị mà là một hàm đã khai báo, hàm hello[]

Khi đó lời gọi hàm welcome[] sẽ tạo ra một hàm mới xxx tương đương với hàm hello[]. Cũng có thể xem xxx như một tên gọi khác của hello[]. Bạn sử dụng hàm kết quả xxx[] giống như sử dụng hello[]

Trong Python, bạn có thể khai báo một hàm bên trong hàm khác. Hàm khai báo trong một hàm khác được gọi là hàm lồng nhau [hàm lồng nhau]

Hãy cùng xem một ví dụ khác

________số 8

Lần này thay vì sử dụng một hàm hello[] build trước, chúng ta tự định nghĩa một hàm hello[] mới nằm trong welcome[]. Hàm hello[] là hàm lồng [hàm con] của welcome[]

Lệnh khai báo hàm hello[] trong hàm welcome[] và trả về hàm hello[] làm kết quả của hàm welcome[] được gọi là đóng

Closure là một hàm khai báo bên trong một hàm khác nhưng sau đó được truyền ra bên ngoài hàm chứa nó [và có thể được sử dụng bởi mã bên ngoài hàm chứa]

Điểm đặc biệt của bao đóng là hàm lồng có thể sử dụng biến và tham số của hàm chứa nó. Trong ví dụ trên, hello[] sử dụng tham số của lời chào của welcome[]

Xây dựng trình trang trí hàm trong Python

Qua hai phần trên bạn đã hiểu các yếu tố cơ bản để tạo ra trình trang trí. Giờ chúng ta cùng vận tải để tự mình tạo ra một chức năng trang trí mới

Hãy cùng thực hiện một ví dụ

def hello[name]:
    "đây là một hàm bình thường"
    print[f'Hello, {name}. Welcome to heaven!']
def welcome[]:
    "đây là một hàm bậc cao, kết quả trả về là một hàm khác"
    return hello
# lời gọi hàm welcome[] sẽ tạo ra một hàm mới xxx tương đương với hàm hello[]
xxx = welcome[]
# xxx có thể xem như là một tên gọi khác của hello[]
xxx['Obama']
5

Trong ví dụ về bạn đã xây dựng hàm bậc cao display_decorator, nhận một hàm khác làm tham số. Yêu cầu của hàm tham số là nhận một chuỗi tham số

Trong hàm display_decorator, bạn tạo một hàm bao đóng[]. Trong trình bao bọc[], bạn thực hiện gọi hàm func[], thêm một số logic trước và sau khi chạy func. Điều đặc biệt là trình bao bọc[] cần có danh sách tham số chung với hàm func[]

def welcome[greeting: 'lời chào']:
    def hello[name: 'tên người']:
        print[f'{greeting}, {name}. Welcome to heaven!']
    return hello
hi = welcome['Hello']
hi['Putin']
5 là thuộc tính chứa tên của đối tượng. Ở đây chúng ta sử dụng
def welcome[greeting: 'lời chào']:
    def hello[name: 'tên người']:
        print[f'{greeting}, {name}. Welcome to heaven!']
    return hello
hi = welcome['Hello']
hi['Putin']
5 để lấy tên công thức chính của tham số hàm

Hàm display_decorator return wrapper[] to results

Trong decorator mẫu, trình bao bọc[] chính là trục xoay vấn đề. to expand features of a function func[], you will instead func[] by wrapper[]. Điều này có thể được xác định theo cách sử dụng cơ bản của decorator

def hello[name]:
    "đây là một hàm bình thường"
    print[f'Hello, {name}. Welcome to heaven!']
def welcome[]:
    "đây là một hàm bậc cao, kết quả trả về là một hàm khác"
    return hello
# lời gọi hàm welcome[] sẽ tạo ra một hàm mới xxx tương đương với hàm hello[]
xxx = welcome[]
# xxx có thể xem như là một tên gọi khác của hello[]
xxx['Obama']
8

Để đơn giản hóa sử dụng hàm trang trí, Python cung cấp cú pháp @. Cú pháp này giúp khung lệnh gọi trang trí với lệnh khai báo hàm

def hello[name]:
    "đây là một hàm bình thường"
    print[f'Hello, {name}. Welcome to heaven!']
def welcome[]:
    "đây là một hàm bậc cao, kết quả trả về là một hàm khác"
    return hello
# lời gọi hàm welcome[] sẽ tạo ra một hàm mới xxx tương đương với hàm hello[]
xxx = welcome[]
# xxx có thể xem như là một tên gọi khác của hello[]
xxx['Obama']
9

Hai cách sử dụng decorator tương đương nhau

Kết quả chạy chương trình như sau

def hello[name]:
    "đây là một hàm bình thường"
    print[f'Hello, {name}. Welcome to heaven!']
def welcome[]:
    "đây là một hàm bậc cao, kết quả trả về là một hàm khác"
    return hello
# lời gọi hàm welcome[] sẽ tạo ra một hàm mới xxx tương đương với hàm hello[]
xxx = welcome[]
# xxx có thể xem như là một tên gọi khác của hello[]
xxx['Obama']
0

Để ý rằng chức năng chính của hàm display[] hay say_hello[] đều chỉ là trong một chuỗi văn bản. Khi được đánh dấu bằng trình trang trí, có thêm logic tự động thực hiện trước và sau khi thực thi hàm

A number of other problems with decorator

At on them ta said about function decorator. a function get a function doing tham số và trả về kết quả của một hàm

Trình trang trí Python còn mở rộng thành lớp trang trí. Nghĩa là bạn có thể xây dựng cả một lớp hoạt động với vai trò trang trí cho hàm. Please view ví dụ sau

def hello[name]:
    "đây là một hàm bình thường"
    print[f'Hello, {name}. Welcome to heaven!']
def welcome[]:
    "đây là một hàm bậc cao, kết quả trả về là một hàm khác"
    return hello
# lời gọi hàm welcome[] sẽ tạo ra một hàm mới xxx tương đương với hàm hello[]
xxx = welcome[]
# xxx có thể xem như là một tên gọi khác của hello[]
xxx['Obama']
1

Kết quả thực thi của hàm hello[‘Obama’] sẽ là

def hello[name]:
    "đây là một hàm bình thường"
    print[f'Hello, {name}. Welcome to heaven!']
def welcome[]:
    "đây là một hàm bậc cao, kết quả trả về là một hàm khác"
    return hello
# lời gọi hàm welcome[] sẽ tạo ra một hàm mới xxx tương đương với hàm hello[]
xxx = welcome[]
# xxx có thể xem như là một tên gọi khác của hello[]
xxx['Obama']
2

Trong ví dụ này, Python sẽ tạo đối tượng của decoclass và truyền hàm hello làm tham số khi khởi động. Phương thức ma thuật

def welcome[greeting: 'lời chào']:
    def hello[name: 'tên người']:
        print[f'{greeting}, {name}. Welcome to heaven!']
    return hello
hi = welcome['Hello']
hi['Putin']
7 giúp lớp hoạt động [được gọi] như một hàm [chính xác hơn, một đối tượng có thể gọi được – loại đối tượng có thể được gọi giống như hàm]

Nếu logic của bạn quá phức tạp và không thể trình bày trong một hàm, bạn có thể cần đến lớp trang trí

Nếu function wrapper[] của bạn đơn giản, bạn có thể sử dụng lambda function

Hàm lambda là loại hàm không có tên và phần thân chỉ được chứa một lệnh duy nhất. Hàm lambda được khai báo với cú pháp như sau

def hello[name]:
    "đây là một hàm bình thường"
    print[f'Hello, {name}. Welcome to heaven!']
def welcome[]:
    "đây là một hàm bậc cao, kết quả trả về là một hàm khác"
    return hello
# lời gọi hàm welcome[] sẽ tạo ra một hàm mới xxx tương đương với hàm hello[]
xxx = welcome[]
# xxx có thể xem như là một tên gọi khác của hello[]
xxx['Obama']
4

Ví dụ

def hello[name]:
    "đây là một hàm bình thường"
    print[f'Hello, {name}. Welcome to heaven!']
def welcome[]:
    "đây là một hàm bậc cao, kết quả trả về là một hàm khác"
    return hello
# lời gọi hàm welcome[] sẽ tạo ra một hàm mới xxx tương đương với hàm hello[]
xxx = welcome[]
# xxx có thể xem như là một tên gọi khác của hello[]
xxx['Obama']
0

Bạn có cách sử dụng hàm lambda làm trình bao bọc cho trình trang trí như sau

def hello[name]:
    "đây là một hàm bình thường"
    print[f'Hello, {name}. Welcome to heaven!']
def welcome[]:
    "đây là một hàm bậc cao, kết quả trả về là một hàm khác"
    return hello
# lời gọi hàm welcome[] sẽ tạo ra một hàm mới xxx tương đương với hàm hello[]
xxx = welcome[]
# xxx có thể xem như là một tên gọi khác của hello[]
xxx['Obama']
1

Bạn cũng có thể ghép các decorator lại với nhau thành chuỗi, được gọi là chaining decorators. Please view ví dụ sau

Chủ Đề