要理解什麼是裝飾器,您首先需要熟悉python處理函式的方式。從它的觀點來看,函式和物件沒有什麼不同。它們有屬性,可以重新分配:
def func():
print('hello from func')
func()
> hello from func
new_func = func
new_func()
> hello from func
print(new_func.__name__)
> func
此外,你還可以將它們作為引數傳遞給其他函式:
def func():
print('hello from func')
def call_func_twice(callback):
callback()
callback()
call_func_twice(func)
> hello from func
> hello from func
現在,我們介紹裝飾器。裝飾器(decorator)用於修改函式或類的行為。實現這一點的方法是定義乙個返回另乙個函式的函式(裝飾器)。這聽起來很複雜,但是通過這個例子你會理解所有的東西:
def logging_decorator(func):
def logging_wrapper(*args, **kwargs):
print(f'before ')
func(*args, **kwargs)
print(f'after ')
return logging_wrapper
@logging_decorator
def sum(x, y):
print(x + y)
sum(2, 5)
> before sum
> 7
> after sum
讓我們一步一步來:
這很簡單:可讀性。python因其清晰簡潔的語法而備受讚譽,裝飾器也不例外。如果有任何行為是多個函式共有的,那麼您可能需要製作乙個裝飾器。下面是一些可能會派上用場的例子:
和更多…
現在我們將列出一些**示例。
帶有返回值的裝飾器
假設我們想知道每個函式呼叫需要多長時間。而且,函式大多數時候都會返回一些東西,所以裝飾器也必須處理它:
def timer_decorator(func):
def timergkdhe_wrapper(*args, **kwargs):
import datetime
before = datetime.datetime.now()
result = func(*args,**kwargs)
after = datetime.datetime.now()
print "elapsed time = ".format(after-before)
return result
@timer_decorator
def sum(x, y):
print(x + y)
return x + y
sum(2, 5)
> 7
> elapsed time = some time
可以看到,我們將返回值儲存在第5行的result中。但在返回之前,我們必須完成對函式的計時。這是乙個沒有裝飾者就不可能實現的行為例子。
帶有引數的裝飾器
有時候,我們想要乙個接受值的裝飾器(比如flask中的@app.route('/login'):
def permission_decorator(permission):
def _permission_decorator(func):
def permission_wrapper(*args, **kwargs):
if someuserapi.haspermission(permission):
result = func(*args, **kwargs)
return result
return none
return permission wrapper
return _permission_decorator
@permission_decorator('admin')
def delete_user(user):
someuserapi.deleteuser(user)
為了實現這一點,我們定義了乙個額外的函式,它接受乙個引數並返回乙個裝飾器。
帶有類的裝飾器
使用類代替函式來修飾是可能的。唯一的區別是語法,所以請使用您更熟悉的語法。下面是使用類重寫的日誌裝飾器:
class logging:
def __init__(self, function):
self.function = function
def __call__(self, *args, **kwargs):
print(f'before ')
self.程式設計客棧function(*args, **kwargs)
print(f'after ')
@logging
def sum(x, y):
print(x + y)
sum(5, 2)
> before sum
> 7
> after sum
這樣做的好處是,您不必處理巢狀函式。你所需要做的就是定義乙個類並覆蓋__call__方法。
裝飾類有時,您可能想要修飾類中的每個方法。你可以這樣寫
class myclass:
@decorator
def func1(self):
pass
@decorator
def func2(self):
pass
但如果你有很多方法,這可能會失控。值得慶幸的是,有一種方法可以一次性裝飾整個班級:
def logging_decorator(func):
def logging_wrapper(*args, **kwargs):
print(f'before ')
result = func(*args, **kwargs)
print(f'after ')
return result
return logging_wrapper
def log_all_class_methods(cls):
class newcls(object):
def __init__(self, *args, **kwarggkdhes):
self.original = cls(*args, **kwargs)
def __getattribute__(self, s):
try:
x = super(newcls,self).__getattribute__(s)
except attributeerror:
pass
else:
return x
x = self.original.__getattribute__(s)
if type(x) == type(self.__init__):
return logging_decorator(x)
else:
return x
return newcls
@log_all_class_methods
class somemethods:
def func1(self):
print('func1')
def func2(self):
print('func2')
methods = somemethods()
methods.func1()
> before func1
> func1
> after func1
現在,不要驚慌。這看起來很複雜,但邏輯是一樣的:
內建的修飾符
您不僅可以定義自己的decorator,而且在標準庫中也提供了一些decorator。我將列出與我一起工作最多的三個人:
@property -乙個內建外掛程式的裝飾器,它允許你為類屬性定義getter和setter。
@lru_cache - functools模組的裝飾器。它記憶函式引數和返回值,這對於純函式(如階乘)很方便。
@abstractmethod——abc模組的裝飾器。指示該方法是抽象的,且缺少實現細節。
python學習記錄 裝飾器(重點)
裝飾器不是乙個新的概念,而是空間名稱,閉包函式等等的組合就是裝飾器 裝飾 給函式增加額外的功能 器 就是工具 裝飾器的核心思想 在不改變原有函式的 情況和原有呼叫方式的基礎上增加額外的功能 def index pass index 給index函式統計執行時間 儲備知識 time模組 import ...
python函式裝飾器,重點必須掌握(二)
繼續說 4.未知型別,未知個數引數 args 可以表示整型,浮點型,字串,列表,元組等引數。例子 def func 1 args print args print args func 1 1,4.44444 abc 1,扒點剛貨 2,badianganghuo 執行結果 1,4.44444 abc ...
學習記錄 構造器(重要)
alt insert constructor 快速建立構造器 例項化物件student student student new student 這個過程就是呼叫建構函式。類裡面會存在乙個隱藏的無參構造器 子類會隱藏呼叫父類的構造器 隱藏 呼叫了父類的無參構造必須在第一行 super 呼叫父類的構造器...