Python裝飾器詳解,詳細介紹它的應用場景


Python裝飾器詳解,詳細介紹它的應用場景

裝飾器的應用場景

  • 附加功能
  • 數據的清理或添加:函數參數類型驗證 @require_ints 類似請求前攔截數據格式轉換 將函數返回字典改為 JSON/YAML 類似響應後篡改為函數提供額外的數據 mock.patch
  • 函數註冊在任務中心註冊一個任務註冊一個帶信號處理器的函數
Python裝飾器詳解,詳細介紹它的應用場景

不同應用場景下裝飾器實現

函數註冊表

簡單註冊表

<code>funcs = []
def register(func):
funcs.append(func)
return func
@register
def a():
return 3

@register
def b():
return 5
# 訪問結果
result = [func() for func in funcs]/<code>

註冊表隔離(使用類的不同實例)

<code>class Registry(object):
def __init__(self):
self._funcs = []

def register(self, func):
self._funcs.append(func)

def run_all(self):
return [func() for func in self._funcs]
r1 = Registry()
r2 = Registry()

@r1.register
def a():
return 3

@r2.register
def b():
return 5


@r1.register
@r2.register/<code>

執行時封裝代碼

類型檢查

<code>from functools import wraps
def require_ints(func):
@wraps(func) # 將func的信息複製給inner
def inner(*args, **kwargs):
for arg list(args) + list(kwargs.values()):
if not isinstance(arg, int:
raise TypeError("{} 只接受int類型參數".format(func.__name__)
return func(*args, **kwargs)
return inner/<code>

用戶驗證

<code>from functools import wraps

class User(object):
def __init__(self, username, email):
self.username = username
self.email = email

class AnonymousUser(object):
def __init__(self):
self.username = self.email = None
def __nonzero__(self): # 將對象轉換為bool類型時調用
return False
def requires_user(func):
@wraps(func)
def inner(user, *args, **kwargs): # 由於第一個參數無法支持self, 該裝飾器不支持裝飾類
if user and isinstance(user, User):
return func(use, *args, **kwargs)
else:
raise ValueError("非合法用戶")
return inner/<code>

輸出格式化

<code>import json
from functools import wraps
def json_output(func): # 將原本func返回的字典格式轉為返回json字符串格式
@wrap(func)
def inner(*args, **kwargs):
return json.dumps(func(*args, **kwargs))
return inner/<code>

異常捕獲

<code>import json
from functools import wraps

class Error1(Exception):
def __init__(self, msg):
self.msg = msg
def __str__(self):
return self.msg

def json_output(func):
@wrap(func)
def inner(*args, **kwargs):
try:
result = func(*args, **kwargs)
except Error1 as ex:
result = {"status": "error", "msg": str(ex)}
return json.dumps(result)
return inner
# 使用方法
@json_ouput
def error():
raise Error1("該條異常會被捕獲並按JSON格式輸出")/<code>

日誌管理

<code>import time
import logging
from functools import wraps

def logged(func):
@wraps(func)
def inner(*args, **kwargs): # *args可以裝飾函數也可以裝飾類
start = time.time()
result = func(*args, **kwargs)

exec_time = time.time() - start
logger = logging.getLoger("func.logged")
logger.warning("{} 調用時間:{:.2} 執行時間:{:.2}s 結果:{}".format(func.__name__, start, exec_time, result)/<code>

帶參數的裝飾器

Python裝飾器詳解,詳細介紹它的應用場景


帶參數的裝飾器相當於一個返回裝飾器的函數,@deco(a=1)在調用@之前會首先執行deco(a=1)得到一個實際的裝飾器, 帶參數的裝飾器deco(a=1)模塊導入時立即執行

裝飾類

為類增加可排序功能(而不通過繼承子類擴充父類方法,比如多個類需要增加此功能時)

<code>import time
from functools import wraps
def sortable_by_created(cls):
original_init = cls.__init__
@wrap(original_init)
def new_init(self, *args, **kwargs):
original_init(*args, **kwargs)
self._created = time.time()
cls.__init__ = new_init

cls.__lt__ = lambda self, other: self._created < other._created
cls.__gt__ = lambda self, other: self._created > other._created
return cls/<code>

也可定義一個SortableByCreated()類, 子類使用多重繼承其父類和SortableByCreated

類型轉換

函數被裝飾後有可能變為一個類的實例,此時為了兼容函數調用,應為所返回的類提供__call__方法

<code>class Task(object):
def __call__(self, *args, **kwargs):
return self.run(*args, **kwargs)
def run(self, *args, **kwargs):
raise NotImplementedError("子類未實現該接口")
def task(func):
class SubTask(Task):
def run(self, *args, **kwargs):
func(*args, **kwargs)
return SubTask()/<code>

第二章 上下文管理器

定義

包裝任意代碼

確保執行的一致性

語法

with語句

__enter__和__exit__方法

<code>class ContextManager(object):
def __init__(self):
self.entered = False
def __enter__(self):
self.entered = True
return self
def __exit__(self, exc_type, exc_instance, traceback):
self.entered = False/<code>

應用場景

資源清理

<code>import pymysql

class DBConnection(object):
def __init__(self, *args, **kwargs):
self.args,self.kwargs = args, kwargs

def __enter__(self):
self.conn = pymysql.connect(*args, **kwargs)
return self.conn.cursor()

def __exit__(self, exc_type, exc_instance, trackback):
self.conn.close()/<code>

異常處理(避免重複)

傳播異常(__exit__中return False)

終止異常(__exit__中return True)

<code>class BubleExceptions(object):
def __enter__(self):
return self
def __exit__(self, exc_type, exc_instance, trackback):
if exc_instance:
print("出現異常: {}".format(exc_instance)
return False # return True終止異常/<code>

處理特定的異常

<code>class HandleValueError(object):
def __enter__(self):
return self
def __exit__(self, exc_type, exc_instance, trackback):
if not exc_type: return True
if issubclass(exc_type, ValueError):
print("處理ValueError: {}".format(exc_instance)
return False/<code>

if issubclass...語句改為if exec_type == ValueError則不處理ValueType的子類異常

也可以根據異常的屬性來判斷是否傳播或終止

更簡單的語法

<code>import contextlib

@contextlib.contextmanager
def acceptable_error_codes(*codes):
try:

yield
except ShellException as exc_instance:
if exc_instance.code not in codes:
raise
pass/<code>

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持我們。

時間: 2020-04-10

python裝飾器使用實例詳解

這篇文章主要介紹了python裝飾器使用實例詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下 python裝飾器的作用就是在不想改變原函數代碼的情況下,增加新的功能.主要應用了python閉包的概念,現在用1個小例子說明 import time def foo(): time.sleep(1) def bar(): time.sleep(2) def show_time(f): def inner(): start_time = time.t

Python3.7 新特性之dataclass裝飾器

Python 3.7中一個令人興奮的新特性是 data classes . 數據類通常是一個主要包含數據的類,儘管實際上沒有任何限制. 它是使用新的 @dataclass 裝飾器創建的,如下所示: from dataclasses import dataclass @dataclass class DataClassCard: rank: str suit: str 此代碼以及本教程中的所有其他示例僅適用於 Python 3.7 及更高版本. 注意: 當然在 Python 3.6 版本也可以使用

Python @property裝飾器原理解析

這篇文章主要介紹了Python @property裝飾器原理解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下 1.通過@property裝飾器,可以直接通過方法名來訪問方法,不需要在方法名後添加一對"()"小括號. class Person: def __init__(self, name): self.__name = name @property def say(self): return self.__name xioabai

python使用裝飾器作日誌處理的方法

裝飾器這東西我看了一會兒才明白,在函數外面套了一層函數,感覺和java裡的aop功能很像:寫了2個裝飾器日誌的例子, 第一個是不帶參數的裝飾器用法示例,功能相當於給函數包了層異常處理,第二個是帶參數的裝飾器用法示例,將日誌輸出到文件. ``` #coding=utf8 import traceback import logging from logging.handlers import TimedRotatingFileHandler def logger(func): def inner(*

python函數裝飾器之帶參數的函數和帶參數的裝飾器用法示例

本文實例講述了python函數裝飾器之帶參數的函數和帶參數的裝飾器用法.分享給大家供大家參考,具體如下: 1. 函數帶多個參數 # 普通的裝飾器, 打印函數的運行時間 def decrator(func): def wrap(*args, **kwargs): start_time = time.time() res = func(*args, **kwargs) end_time = time.time() print('運行時間為', end_time-start_time) return

Python裝飾器詳解,詳細介紹它的應用場景


python中property和setter裝飾器用法

作用:調用方法改為調用對象, 比如 : p.set_name() 改為 p.set_name 區別:前者改變get方法,後者改變set方法 效果圖: 代碼: class Person: def __init__(self,name): self._name = name def get_name(self): return self._name def set_name(self,name): self._name = name p = Person('小黑') print(p.get_name

python裝飾器練習題及答案

這篇文章主要介紹了python裝飾器練習題及答案,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下 一:編寫裝飾器,為多個函數加上認證的功能(用戶的賬號密碼) 要求登錄成功一次,後續的函數都無需輸入用戶名和密碼 FLAG=False#此時還未登錄 全局變量 寫這個步驟的意義在於:方便 知道已經登錄成功了,就不再重複登錄 def login(func):#為多個函數加上的認證功能 def inner(*args,**kwargs):#加上裝飾器 gl

python裝飾器實例大詳解

一.作用域 在python中,作用域分為兩種:全局作用域和局部作用域. 全局作用域是定義在文件級別的變量,函數名.而局部作用域,則是定義函數內部. 關於作用域,我們要理解兩點: a.在全局不能訪問到局部定義的變量 b.在局部能夠訪問到全局定義的變量,但是不能修改全局定義的變量(當然有方法可以修改) 下面我們來看看下面實例: x = 1 def funx(): x = 10 print(x) # 打印出10 funx() print(x) # 打印出1 如果局部沒有定義變量x,那麼函數內部會從內往

Python 裝飾器深入理解

講 Python 裝飾器前,我想先舉個例子,雖有點汙,但跟裝飾器這個話題很貼切. 每個人都有的內褲主要功能是用來遮羞,但是到了冬天它沒法為我們防風禦寒,咋辦?我們想到的一個辦法就是把內褲改造一下,讓它變得更厚更長,這樣一來,它不僅有遮羞功能,還能提供保暖,不過有個問題,這個內褲被我們改造成了長褲後,雖然還有遮羞功能,但本質上它不再是一條真正的內褲了.於是聰明的人們發明長褲,在不影響內褲的前提下,直接把長褲套在了內褲外面,這樣內褲還是內褲,有了長褲後寶寶再也不冷了.裝飾器就像我們這裡說的長褲,在不

使用Python裝飾器在Django框架下去除冗餘代碼的教程

Python裝飾器是一個消除冗餘的強大工具.隨著將功能模塊化為大小合適的方法,即使是最複雜的工作流,裝飾器也能使它變成簡潔的功能. 例如讓我們看看Django web框架,該框架處理請求的方法接收一個方法對象,返回一個響應對象: def handle_request(request): return HttpResponse("Hello, World") 我最近遇到一個案例,需要編寫幾個滿足下述條件的api方法: 返回json響應 如果是GET請求,那麼返回錯誤碼 做為一個註冊api

深入理解Python裝飾器

裝飾器簡介: 裝飾器(decorator)是一種高級Python語法.裝飾器可以對一個函數.方法或者類進行加工.在Python中,我們有多種方法對函數和類進行加工,比如在Python閉包中,我們見到函數對象作為某一個函數的返回結果.相對於其它方式,裝飾器語法簡單,代碼可讀性高.因此,裝飾器在Python項目中有廣泛的應用. 裝飾器最早在Python 2.5中出現,它最初被用於加工函數和方法這樣的可調用對象(callable object,這樣的對象定義有__call__方法).在Python 2

python裝飾器初探(推薦)

一.含有一個裝飾器 #encoding: utf-8 ############含有一個裝飾器######### def outer(func): def inner(*args, **kwargs):#要裝飾f1(),這裡用這倆形式參數,可以接受任意個參數,不管f1定義幾個參數 print "1" r = func(*args, **kwargs)#這裡要用func,不要用f1 print "2" return r return inner @outer #這裡ou

深入淺出分析Python裝飾器用法

本文實例講述了Python裝飾器用法.分享給大家供大家參考,具體如下: 用類作為裝飾器 示例一 最初代碼: class bol(object): def __init__(self, func): self.func = func def __call__(self): return "{}".format(self.func()) class ita(object): def __init__(self, func): self.func = f

Python裝飾器基礎詳解

裝飾器(decorator)是一種高級Python語法.裝飾器可以對一個函數.方法或者類進行加工.在Python中,我們有多種方法對函數和類進行加工,比如在Python閉包中,我們見到函數對象作為某一個函數的返回結果.相對於其它方式,裝飾器語法簡單,代碼可讀性高.因此,裝飾器在Python項目中有廣泛的應用. 前面快速介紹了裝飾器的語法,在這裡,我們將深入裝飾器內部工作機制,更詳細更系統地介紹裝飾器的內容,並學習自己編寫新的裝飾器的更多高級語法. 什麼是裝飾器 裝飾是為函數和類指定管理代碼的一種

python裝飾器與遞歸算法詳解

1.python裝飾器 剛剛接觸python的裝飾器,簡直懵逼了,直接不懂什麼意思啊有木有,自己都忘了走了多少遍Debug,查了多少遍資料,猜有點點開始明白了.總結了一下解釋得比較好的,通俗易懂的來說明一下: 小P閒來無事,隨便翻看自己以前寫的一些函數,忽然對一個最最最基礎的函數起了興趣: def sum1(): sum = 1 + 2 print(sum) sum1() 此時小P想看看這個函數執行用了多長時間,所以寫了幾句代碼插進去了: import time def sum1(): star

Python裝飾器實現幾類驗證功能做法實例

最近新需求來了,要給系統增加幾個資源權限.儘量減少代碼的改動和程序的複雜程度.所以還是使用裝飾器比較科學 之前用了一些登錄驗證的現成裝飾器模塊.然後仿寫一些用戶管理部分的權限裝飾器. 比如下面這種 def permission_required(permission): def decorator(f): @wraps(f) def decorated_function(*args, **kwargs): if not current_user.can(permission): abort(40

Python裝飾器入門學習教程(九步學習)

裝飾器(decorator)是一種高級Python語法.裝飾器可以對一個函數.方法或者類進行加工.在Python中,我們有多種方法對函數和類進行加工,比如在Python閉包中,我們見到函數對象作為某一個函數的返回結果.相對於其它方式,裝飾器語法簡單,代碼可讀性高.因此,裝飾器在Python項目中有廣泛的應用. 這是在Python學習小組上介紹的內容,現學現賣.多練習是好的學習方式. 第一步:最簡單的函數,準備附加額外功能 # -*- coding:gbk -*- '''示例1: 最簡單的函數,表


分享到:


相關文章: