2013-02-05 24 views
25

Tôi muốn sử dụng một trình trang trí để xử lý việc kiểm tra các chức năng khác nhau (chủ yếu là các chức năng xem Django, nhưng không độc quyền). Để thực hiện điều này, tôi muốn có thể kiểm tra chức năng sau khi thực thi - tức là chức năng chạy như bình thường và nếu nó trả về mà không có ngoại lệ, thì trình trang trí sẽ ghi lại sự kiện.Làm cách nào để tôi có được trình trang trí Python để chạy sau khi chức năng trang trí đã hoàn thành?

Cái gì như:

@audit_action(action='did something') 
def do_something(*args, **kwargs): 
    if args[0] == 'foo': 
     return 'bar' 
    else: 
     return 'baz' 

đâu audit_action sẽ chỉ chạy sau khi chức năng đã hoàn thành.

Trả lời

26

Trang trí thường trả về hàm bao bọc; chỉ cần đặt logic của bạn trong hàm wrapper sau khi gọi hàm được bọc.

def audit_action(action): 
    def decorator_func(func): 
     def wrapper_func(*args, **kwargs): 
      # Invoke the wrapped function first 
      retval = func(*args, **kwargs) 
      # Now do something here with retval and/or action 
      print 'In wrapper_func, handling action {!r} after wrapped function returned {!r}'.format(action, retval) 
      return retval 
     return wrapper_func 
    return decorator_func 

Vì vậy audit_action(action='did something') là một nhà máy trang trí mà trả về một scoped decorator_func, được sử dụng để trang trí do_something (do_something = decorator_func(do_something)) của bạn.

Sau khi trang trí, tài liệu tham khảo do_something của bạn đã được thay thế bằng wrapper_func. Gọi số wrapper_func() làm cho số do_something() gốc được gọi, sau đó mã của bạn trong trình bao bọc func có thể thực hiện.

Đoạn mã trên, kết hợp với chức năng ví dụ của bạn, cung cấp cho các đầu ra sau đây:

>>> do_something('foo') 
In wrapper_func, handling action 'did something' after wrapped function returned 'bar' 
'bar' 
+2

Bạn không có ý tưởng bao nhiêu kết hợp khác nhau của trang trí, wrapper, func và retvals Tôi đã sử dụng hết để có được điều này để làm việc. Cảm ơn không chỉ cho mã, nhưng để giải thích. –

3

trang trí của bạn có thể xử lý nó ở đây chính nó, như

def audit_action(function_to_decorate): 
    def wrapper(*args, **kw): 
     # Calling your function 
     output = function_to_decorate(*args, **kw) 
     # Below this line you can do post processing 
     print "In Post Processing...." 
    return wrapper 
+0

Ví dụ OP được đăng sử dụng một nhà máy trang trí được gọi với đối số 'action'. Bạn cần một lớp phạm vi hoặc một lớp học .. –

+0

cập nhật câu trả lời theo ví dụ của OP :) – avasal

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