我終於弄懂了Python的裝飾器(四)

此係列文檔:python

1. 我終於弄懂了Python的裝飾器(一)緩存

2. 我終於弄懂了Python的裝飾器(二)app

3. 我終於弄懂了Python的裝飾器(三)異步

4. 我終於弄懂了Python的裝飾器(四)函數

4、裝飾器的用法

通用裝飾器(這裏有一篇文檔要補充)

如要製做通用裝飾器(不管參數如何,您均可以將其應用於任何函數或方法),則只需使用*args, **kwargspost

def a_decorator_passing_arbitrary_arguments(function_to_decorate):
    #包裝器接受任何參數(這部分能夠參考文檔:+++++++補充文檔+++++++++++++++)
    def a_wrapper_accepting_arbitrary_arguments(*args, **kwargs):
        print("Do I have args?:")
        print(args)
        print(kwargs)
        function_to_decorate(*args, **kwargs)
    return a_wrapper_accepting_arbitrary_arguments

@a_decorator_passing_arbitrary_arguments
def function_with_no_argument():
    print("Python is cool, no argument here.")

function_with_no_argument()
#輸出:
#Do I have args?:
#()
#{}
#Python is cool, no argument here.

@a_decorator_passing_arbitrary_arguments
def function_with_arguments(a, b, c):
    print(a, b, c)

function_with_arguments(1,2,3)
#輸出:
#Do I have args?:
#(1, 2, 3)
#{}
#1 2 3 

@a_decorator_passing_arbitrary_arguments
def function_with_named_arguments(a, b, c, platypus="Why not ?"):
    print("Do {0}, {1} and {2} like platypus? {3}".format(a, b, c, platypus))

function_with_named_arguments("Bill", "Linus", "Steve", platypus="Indeed!")
#輸出:
#Do I have args ? :
#('Bill', 'Linus', 'Steve')
#{'platypus': 'Indeed!'}
#Do Bill, Linus and Steve like platypus? Indeed!

class Mary(object):

    def __init__(self):
        self.age = 31

    @a_decorator_passing_arbitrary_arguments
    def sayYourAge(self, lie=-3): # You can now add a default value
        print("I am {0}, what did you think?".format(self.age + lie))

m = Mary()
m.sayYourAge()
#輸出:
# Do I have args?:
#(<__main__.Mary object at 0xb7d303ac>,)
#{}
#I am 28, what did you think?

最佳作法:裝飾器

注意:ui

  • 裝飾器是在Python 2.4中引入的,所以請確保您的代碼將在> = 2.4上運行。
  • 裝飾器使函數調用變慢。(請記住這點)
  • 您不能取消裝飾功能。(有一些技巧,能夠建立能夠被刪除的裝飾器,可是沒有人使用它們。)所以,一旦裝飾了一個函數,就對全部代碼進行了裝飾。
  • 裝飾器包裝函數,這會使它們難以調試。(這在Python> = 2.5時有所調整;請參見如下內容。)

functools模塊是在Python 2.5中引入的。
它包括函數functools.wraps(),該函數將修飾後的函數的名稱,模塊和文檔字符串複製到其包裝器中。調試

(有趣的事是:functools.wraps()也是一個裝飾器!)code

#爲了進行調試,stacktrace將向您顯示函數__name__
def foo():
    print("foo")

print(foo.__name__)
#輸出: foo

#使用裝飾器時,輸出的信息會變得凌亂,再也不是foo,而是wrapper
def bar(func):
    def wrapper():
        print("bar")
        return func()
    return wrapper

@bar
def foo():
    print("foo")

print(foo.__name__)
#輸出: wrapper

# "functools" can help for that

import functools

def bar(func):
    # We say that "wrapper", is wrapping "func"
    # and the magic begins
    @functools.wraps(func)
    def wrapper():
        print("bar")
        return func()
    return wrapper

@bar
def foo():
    print("foo")

print(foo.__name__)
#outputs: foo

Python自己提供了一些裝飾:propertystaticmethod,等。orm

  • Django使用裝飾器來管理緩存和查看權限。
  • 僞造的內聯異步函數調用。

如何使用鏈式裝飾器?

# 大膽的使用鏈式裝飾器吧
def makebold(fn):
    # The new function the decorator returns
    def wrapper():
        # Insertion of some code before and after
        return "<b>" + fn() + "</b>"
    return wrapper

# The decorator to make it italic
def makeitalic(fn):
    # The new function the decorator returns
    def wrapper():
        # Insertion of some code before and after
        return "<i>" + fn() + "</i>"
    return wrapper

@makebold
@makeitalic
def say():
    return "hello"

print(say())
#輸出: <b><i>hello</i></b>

# This is the exact equivalent to 
def say():
    return "hello"
say = makebold(makeitalic(say))

print(say())
#輸出: <b><i>hello</i></b>

如今,您能夠暫時放下開心的心情,咱們來動動腦筋,看看裝飾器的高級用法。


原文連接:https://stackoverflow.com/que...

本文首發於 BigYoung小站
相關文章
相關標籤/搜索