Python的神奇功能——函数装饰器MetaClass
生活随笔
收集整理的這篇文章主要介紹了
Python的神奇功能——函数装饰器MetaClass
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
Python中的裝飾器,會讓很多人望而卻步。不要被它嚇跑,啃下它,其實超有用,也沒有想象中難。
-
所謂的裝飾器,其實就是通過裝飾器函數,來修改原函數的一些功能,使得原函數不需要修改。
-
Python的裝飾器類似于Spring的殺手锏之一 AOP(Aspect Oriented Programming)面向切面的編程。把特別復雜的邏輯功能進行切片分層完成,比如日志記錄,在一個函數的調用前后執行,相當于wrapper包裝起來;
-
**裝飾器分類:函數裝飾器,類裝飾器。**裝飾器通常運用在身份認證、日志記錄、輸入合理性檢查以及緩存等多個領域中。合理使用裝飾器,往往能極大地提高程序的可讀性以及運行效率。
函數
- 把函數賦予變量
- 把函數當作參數
- 函數嵌套,函數里定義函數
- 閉包,函數中返回函數對象
# 函數賦值給變量
def func(message):print('Got a message: {}'.format(message))send_message = func
send_message('hello world')
# 同下邊
send_message = func("hello world")# 函數當作參數
def get_message(message):return 'Got a message: ' + messagedef root_call(func, message):print(func(message))root_call(get_message, 'hello world')# 函數嵌套
def func(message):def get_message(message):print('Got a message: {}'.format(message))return get_message(message)func('hello world')# 閉包
def func_closure():def get_message(message):print('Got a message: {}'.format(message))return get_messagesend_message = func_closure()
send_message('hello world')
裝飾器
- 簡單裝飾器
- 類裝飾器(原函數greet的元數據信息被改變,用 functiontools中的@functools.wraps(func),它會幫助保留原函數的元信息(也就是將原函數的元信息,拷貝到對應的裝飾器函數里)。)
- 帶有參數的裝飾器 (自定義參數 *args和kwargs,作為裝飾器內部函數 wrapper() 的參數。*args和kwargs,表示接受任意數量和類型的參數 )
- 裝飾器嵌套(從內到外執行)
- 登錄校驗裝飾器
- 日志裝飾器
# 簡單裝飾器
def my_decorator(func):def wrapper():print('wrapper of decorator')func()return wrapper@my_decorator
def greet():print('hello world')# my_decorator() 就是一個裝飾器,它把真正需要執行的函數 greet() 包裹在其中,并且改變了它的行為,但是原函數 greet() 不變。
# @,我們稱之為語法糖,@my_decorator就相當于greet=my_decorator(greet)語句
# greet = my_decorator(greet)
greet()# 帶有參數的裝飾器
# 我們會把*args和**kwargs,作為裝飾器內部函數 wrapper() 的參數。*args和**kwargs,表示接受任意數量和類型的參數
def my_decorator(func):def wrapper(message):print('wrapper of decorator')func(message)return wrapper@my_decorator
def greet(message):print(message)greet('hello world')# 帶有自定義參數的裝飾器
# 原函數greet的元數據信息被改變,用 functiontools中的@functools.wraps(func),它會幫助保留原函數的元信息(也就是將原函數的元信息,拷貝到對應的裝飾器函數里)。
import functoolsdef repeat(num):def my_decorator(func):@functools.wraps(func)def wrapper(*args, **kwargs):for i in range(num):print('wrapper of decorator')func(*args, **kwargs)return wrapperreturn my_decorator@repeat(4)
def greet(message):print(message)greet('hello world')
print(greet.__name__)# 類裝飾器
# 類裝飾器主要依賴于函數__call__(),每當你調用一個類的示例時,函數__call__()就會被執行一次。class Count:def __init__(self, func):self.func = funcself.num_calls = 0def __call__(self, *args, **kwargs):self.num_calls += 1print('num of calls is: {}'.format(self.num_calls))return self.func(*args, **kwargs)@Count
def example():print("hello world")example()
example()# 裝飾器嵌套 從外到里執行# @decorator1
# @decorator2
# @decorator3
# def func():
# print()
# 同 decorator1(decorator2(decorator3(func)))import functoolsdef my_decorator1(func):@functools.wraps(func)def wrapper(*args, **kwargs):print('execute decorator1')func(*args, **kwargs)return wrapperdef my_decorator2(func):@functools.wraps(func)def wrapper(*args, **kwargs):print('execute decorator2')func(*args, **kwargs)return wrapper@my_decorator1
@my_decorator2
def greet(message):print(message)greet('hello world')# 登錄校驗裝飾器
# import functools# def authenticate(func):
# @functools.wraps(func)
# def wrapper(*args, **kwargs):
# request = args[0]
# if check_user_logged_in(request): # 如果用戶處于登錄狀態
# return func(*args, **kwargs) # 執行函數post_comment()
# else:
# raise Exception('Authentication failed')
# return wrapper# @authenticate
# def post_comment(request)
# print(1)# 日志裝飾器import time
import functoolsdef log_execution_time(func):@functools.wraps(func)def wrapper(*args, **kwargs):start = time.perf_counter()res = func(*args, **kwargs)end = time.perf_counter()print('{} took {} ms'.format(func.__name__, (end - start) * 1000))return resreturn wrapper@log_execution_time
def calculate_similarity(items):print('')calculate_similarity(1)
MetaClass
裝飾器像AOP,metaclass像反射機制
在生成層面中:類裝飾器會調用__call__方法;在使用metaclass實例化生成類的時候也是調用了__call__方法;
總結
以上是生活随笔為你收集整理的Python的神奇功能——函数装饰器MetaClass的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Python的必学技术——Jupyter
- 下一篇: Python全局解释器锁GIL与多线程