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

Bigyoungs發表於2020-07-09

此係列文件:

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

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

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

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

三、裝飾器應該在何時發揮作用?

現在有個大問題:

我可以使用裝飾器做什麼?

裝飾器看起來很酷而且功能強大,但是展示一個實際的例子會更清晰。
使用的場景有1000種可能性。但是經典用法:

  • 通過外部庫來擴充套件函式的行為(在您不能對其進行修改的情況下)。
  • 用於除錯(您不希望對其進行修改,因為它是臨時的)。
  • 重複使用功能,可以通過裝飾器來加到其他多個函式上。

您可以使用它們以鏈式的方式擴充套件多個功能,如下所示:

def benchmark(func):
    """
    裝飾器,列印函式執行花費的時間。
    """
    import time
    def wrapper(*args, **kwargs):
        t = time.clock()
        res = func(*args, **kwargs)
        print("{0} {1}".format(func.__name__, time.clock()-t))
        return res
    return wrapper


def logging(func):
    """
    裝飾器,記錄指令碼的活動。(它實際上只是列印出來,但可能是在記錄日誌!)
    """
    def wrapper(*args, **kwargs):
        res = func(*args, **kwargs)
        print("{0} {1} {2}".format(func.__name__, args, kwargs))
        return res
    return wrapper


def counter(func):
    """
    裝飾器,計算並列印執行功能的次數
    """
    def wrapper(*args, **kwargs):
        wrapper.count = wrapper.count + 1
        res = func(*args, **kwargs)
        print("{0} has been used: {1}x".format(func.__name__, wrapper.count))
        return res
    wrapper.count = 0
    return wrapper

@counter
@benchmark
@logging
def reverse_string(string):
    return str(reversed(string))

print(reverse_string("Able was I ere I saw Elba"))
print(reverse_string("A man, a plan, a canoe, pasta, heros, rajahs, a coloratura, maps, snipe, percale, macaroni, a gag, a banana bag, a tan, a tag, a banana bag again (or a camel), a crepe, pins, Spam, a rut, a Rolo, cash, a jar, sore hats, a peon, a canal: Panama!"))

#輸出:
#reverse_string ('Able was I ere I saw Elba',) {}
#wrapper 0.0
#wrapper has been used: 1x 
#ablE was I ere I saw elbA
#reverse_string ('A man, a plan, a canoe, pasta, heros, rajahs, a coloratura, maps, snipe, percale, macaroni, a gag, a banana bag, a tan, a tag, a banana bag again (or a camel), a crepe, pins, Spam, a rut, a Rolo, cash, a jar, sore hats, a peon, a canal: Panama!',) {}
#wrapper 0.0
#wrapper has been used: 2x
#!amanaP :lanac a ,noep a ,stah eros ,raj a ,hsac ,oloR a ,tur a ,mapS ,snip ,eperc a ,)lemac a ro( niaga gab ananab a ,gat a ,nat a ,gab ananab a ,gag a ,inoracam ,elacrep ,epins ,spam ,arutaroloc a ,shajar ,soreh ,atsap ,eonac a ,nalp a ,nam A

當然,使用裝飾器的好處是您可以立即在幾乎所有內容上使用它們而無需重寫。比如:

@counter
@benchmark
@logging
def get_random_futurama_quote():
    from urllib import urlopen
    result = urlopen("http://subfusion.net/cgi-bin/quote.pl?quote=futurama").read()
    try:
        value = result.split("<br><b><hr><br>")[1].split("<br><br><hr>")[0]
        return value.strip()
    except:
        return "No, I'm ... doesn't!"


print(get_random_futurama_quote())
print(get_random_futurama_quote())

#輸出:
#get_random_futurama_quote () {}
#wrapper 0.02
#wrapper has been used: 1x
#The laws of science be a harsh mistress.
#get_random_futurama_quote () {}
#wrapper 0.01
#wrapper has been used: 2x
#Curse you, merciful Poseidon!

本文首發於BigYoung小站

相關文章