2014-12-07 15 views
36
def make_bold(fn): 
    return lambda : "<b>" + fn() + "</b>" 

def make_italic(fn): 
    return lambda : "<i>" + fn() + "</i>" 

@make_bold 
@make_italic 
def hello(): 
    return "hello world" 

helloHTML = hello() 

Output: "<b><i>hello world</i></b>"Decorator thực hiện lệnh

tôi khoảng hiểu về trang trí và làm thế nào nó hoạt động với một trong số đó ở hầu hết các ví dụ.

Trong ví dụ này, có 2 trong số đó. Từ đầu ra, có vẻ như @make_italic thực hiện trước tiên, sau đó @make_bold.

Điều này có nghĩa là đối với các chức năng được trang trí, trước tiên nó sẽ chạy hàm đầu tiên sau đó chuyển sang đầu trang cho các trang trí khác? Giống như @make_italic trước hết là @make_bold, thay vì ngược lại.

Vì vậy, điều này có nghĩa rằng nó khác với tiêu chuẩn của phương pháp tiếp cận từ trên xuống trong hầu hết các ngôn ngữ lập trình? Chỉ cho trường hợp trang trí này? Hoặc là tôi sai?

+2

vâng nó bắt đầu từ dưới lên qua kết quả cho –

Trả lời

58

Trang trí bọc chức năng chúng được trang trí. Vì vậy, make_bold được trang trí kết quả của trang trí make_italic, được trang trí theo chức năng hello.

Cú pháp @decorator thực sự chỉ là cú pháp; như sau:

@decorator 
def decorated_function(): 
    # ... 

thực sự được thực hiện như sau:

def decorated_function(): 
    # ... 
decorated_function = decorator(decorated_function) 

thay thế các đối tượng gốc decorated_function với bất cứ điều gì decorator() trả lại.

Trình trang trí xếp chồng lặp lại quy trình đó ra ngoài.

Vì vậy, mẫu của bạn:

@make_bold 
@make_italic 
def hello(): 
    return "hello world" 

có thể được mở rộng để:

def hello(): 
    return "hello world" 
hello = make_bold(make_italic(hello)) 

Khi bạn gọi hello() bây giờ, bạn đang gọi đối tượng được trả về bởi make_bold(), thực sự. make_bold() trả lại số lambda gọi hàm make_bold được bọc, là giá trị trả lại là make_italic(), cũng là một lambda gọi là số hello() gốc. Mở rộng tất cả các cuộc gọi bạn nhận được:

hello() = lambda : "<b>" + fn() + "</b>" # where fn() -> 
    lambda : "<i>" + fn() + "</i>" # where fn() -> 
     return "hello world" 

nên sản lượng trở thành:

"<b>" + ("<i>" + ("hello world") + "</i>") + "</b>" 
+0

hôm sau tôi hiểu. Nhưng điều này có nghĩa là khi có 2 trình bao bọc trong trường hợp này, IDE sẽ tự động phát hiện và bọc kết quả của trình bao bọc đầu tiên? Bởi vì tôi nghĩ rằng '@make_bold #make_bold = make_bold (hello)' '@make_italiC#make_italic = make_italic (hello)'? Tôi không chắc chắn nếu dựa trên điều này, nó sẽ quấn kết quả đầu tiên. Hoặc đối với trường hợp này của 2 trình bao bọc, IDE sẽ sử dụng 'make_bold (make_italic (hello))' như bạn đã đề cập thay vì những gì tôi đã chia sẻ? – Newbie

+0

@Newbie: IDE của bạn không có gì ở đây; nó là * Python * mà gói.Tôi đã cho bạn thấy trong ví dụ cuối cùng của tôi rằng 'make_bold()' kết thúc đầu ra của 'make_italic()', được sử dụng để bọc 'hello', do đó tương đương với' make_bold (make_italic (hello)) '. –

+0

Bạn có thể cung cấp một phiên bản của mã này mà không cần sử dụng lambda không? Tôi đã thử .format nhưng không hoạt động. Và tại sao lambda được sử dụng trong ví dụ này? Tôi đang cố gắng để hiểu lambda và làm thế nào nó hoạt động trong ví dụ này nhưng vẫn còn có vấn đề. Tôi nhận được rằng lambda giống như một chức năng dòng có thể được thông qua dễ dàng hơn nhiều so với các chỉ tiêu của chức năng def? – Newbie

Các vấn đề liên quan