Python 需要這個裝飾器!

jhong
程式愛好者
Published in
4 min readMar 16, 2021

有時你想要修改既有的函式,但不想更改它的原始碼…………

什麼是裝飾器 (Decorator) ?

  • 也是一種函式
  • 可以接受函式作為參數
  • 可以返回函式
  • 當接收一個函式時,可以內部對其進行處理,並回傳一個新的函式,動態的增強函數的功能
  • 在不改變函式結構的情況添加新功能,用簡單的方式修改它、重新定義它

裝飾器在裝飾什麼 ?

裝飾器是一種設計模式 (Design Pattern),常用於有切面 (Aspect) 場景當中。裝飾器可以簡化大量函式中相同的代碼並重複使用。概括地說,裝飾器的作用就是為已經存在的對象添加額外的功能。這種程式計方式被稱為面向切面的編程 (Aspect-Oriented Programming)。

裝飾器的定義

def out(func):                        # 外圍函式
def inter(*args, **kwargs): # 內部函式
return func(*args, **kwargs)
return inter # 外圍函式返回內部函式

實作一個簡單的裝飾器

如何自訂一個裝飾器,請看以下例子:

def check_str(func):
def inner():
print(‘Hello’)
return func()
return inner
@check_str
def say():
print(‘World’)
say()結果顯示如下
Hello
World

是不是很簡單就可以定義自已需要的裝飾器呢?

From: GIPHY

裝飾器的用法

  • 將被調用的函式直接作為參數傳入裝飾器的外圍函式括弧
  • 將裝飾器與被調用函式綁定在一起
  • @ 符號加上裝飾器函式放在被調用函式的上一行可以直接套用執行

@ 這是 Python 的語法糖,可以讓你的程序變得更簡潔,而 @ 是代表什麼呢?請見以下例子:

say = check_str(say)

上述可以說明 @ 的功用就是將 say 丟到 check_ str( ) 中,而 check_ str ( ) 就是將丟進來的參數 say 綁在一起後傳出。所以最外面的 say 所接收到的東西就是包裝後的 inner( ) ,呼叫 say 時其實是呼叫 inner( ) 所以會先印出 Hello ,再執行方法 say( ) 完成裝飾。

函式有參數?

如果說裝飾器所裝的函式需要輸入參數該如何處理呢? 接收函式,內部對其處理,並回傳值,如何處理請看下列例子:

def check_str(func):
def inner(*args, **kwargs):
result = func(*args, **kwargs)
if result == ‘Hello’:
return ‘%s, World’ % result
else:
return ‘%s, Nice to meet you’ % result
return inner
@check_str
def test(data):
return data
result = test(‘Hello’)
print(result)
result = test(‘Hi’)
print(result)
結果顯示如下︰
Hello, World
Hi, Nice to meet you

裝飾器也有參數?

如果想要在裝飾器上輸入參數該怎麼辦呢? 請看下列例子:

def check_str(msg):
def outer(func):
def inner(*args, **kwargs):
print(msg)
return func(*args, **kwargs)
return inner
return outer
@check_str(‘Hello’)
def say(msg):
print(msg)
say(‘World’)結果將顯示如下︰
Hello
World

Decorator 被大量廣泛的使用在各種場景 如插入日誌、性能測試、事務處理、除錯等,具有幾個最主要的優點:

  • 程式碼簡潔易讀
  • 程式碼重複率低
  • 封裝效果好
  • 靈活使用

因為篇幅有限,提供非常簡單的小例子讓大家參考,Decorator 如果結合各種寫法,相信一定會更能感受除了上述簡單的小範例外,帶來的各種優點!以上就是 Decorator 簡單用法介紹,事實上關於 Decorator 還有許多進階應用可以去發掘 !

--

--