小編寫這篇文章的一個主要目的,主要是給大家去做一個相關的解答,解答的內容主要是涉及到python一些相關事宜,主要是給大家詳解的是Python Decorator的一些相關事宜,比如講一下他們的底層原理,關于設計模式演繹過程,下面就給大家詳細解答下。
關于代理模式、裝飾模式
設計模式中經常提到的代理模式、裝飾模式,這兩種叫法實際上是說的同一件事,只是側重點有所不同而已。
這兩者都是通過在原有對象的基礎上封裝一層對象,通過調用封裝后的對象而不是原來的對象來實現代理/裝飾的目的。
例如:(以Java為例)
public class CountProxy implements Count{ private CountImpl countImpl; public CountProxy(CountImpl countImpl){ this.countImpl=countImpl; } Override public void queryCount(){ System.out.println("事務處理之前"); //調用委托類的方法; countImpl.queryCount(); System.out.println("事務處理之后"); } Override public void updateCount(){ System.out.println("事務處理之前"); //調用委托類的方法; countImpl.updateCount(); System.out.println("事務處理之后"); } }
在這個例子中CountProxy是對CountImpl的封裝。
使用者通過CountProxy.queryCount方法來調用CountImpl.queryCount方法,這被稱為代理,即CountProxy是代理類,CountImpl是被代理類。
在CountProxy.queryCount方法中,可以在CountImpl.queryCount方法調用之前和之后添加一些額外的操作,被稱為裝飾,即CountProxy是裝飾類,CountImpl是被裝飾類。
如果強調通過CountProxy對CountImpl進行代理的作用,則稱為代理模式;
如果強調通過CountProxy對CountImpl增加額外的操作,則稱為裝飾模式;
不論是哪種稱呼,其本質都在于對原有對象的封裝。
其封裝的目的在于增強所封裝對象的功能或管理所封裝的對象。
從上面的例子也可以發現,代理/封裝所圍繞的核心是可調用對象(比如函數)。
Python中的代理/裝飾
Python中的可調用對象包括函數、方法、實現了__call__方法的類。
Python中的函數也是對象,可以作為高階函數的參數傳入或返回值返回。
因此,當代理/裝飾的對象是函數時,可以使用高階函數來對某個函數進行封裝。
例如:
def query_count_proxy(fun,name,age): print('do something before') rv=fun(name,age) print('do something after') return rv def query_count(name,age): print('name is%s,age is%d'%(name,age)) query_count_proxy(query_count,'Lee',20)
但是,這個例子中,query_count函數作為參數傳入query_count_proxy函數中,并在query_count_proxy函數中被調用,其結果作為返回值返回。這就完成了代理的功能,同時,在調用query_count函數的前后,我們還增加了裝飾代碼。
但是,query_count_proxy的函數參數與query_count不一樣了,理想的代理應該保持接口一致才對。
為了保持一致,我們可以利用高階函數可以返回函數的特點來完成:
def query_count_proxy(fun): def wrapper(name,age): print('do something before') rv=fun(name,age) print('do something after') return rv return wrapper def query_count(name,age): print('name is%s,age is%d'%(name,age)) query_count_proxy(query_count)('Lee',20)
修改后的例子,query_count_proxy僅負責接受被代理的函數query_count作為參數,同時,返回一個函數對象wrapper作為返回值,真正的封裝動作在wrapper這個函數中完成。
此時,如果調用query_count_proxy(query_count)就得到了wrapper函數對象,則,執行query_count_proxy(query_count)('Lee',20)就相當于執行了wrapper('Lee',20)。
但是可以看到,query_count_proxy(query_count)('Lee',20)這種使用方法,仍然不能保證一致。
為了保持一致,我們需要利用Python中對象與其名稱可以動態綁定的特點。不使用query_count_proxy(quer_count)('Lee',20)來調用代理函數,而是使用下面兩句:
1
2
query_count=query_count_proxy(query_count) query_count('Lee',20)
執行query_count_proxy(query_count)生成wrapper函數對象,將這個對象通過query_count=query_count_proxy(query_count)綁定到query_count這個名字上來,這樣執行query_count('Lee',20)時,其實執行的是wrapper('Lee',20)。
這么做的結果就是:使用代理時調用query_count('Lee',20)與不使用代理時調用query_count('Lee',20)對使用者而言保持不變,不用改變代碼,但是在真正執行時,使用的是代理/裝飾后的函數。
這里,基本利用Python的高階函數及名稱綁定完成了代理/裝飾的功能。
還有什么不理想的地方呢?
對,就是query_count=query_count_proxy(query_count),因為這句既不簡潔,又屬于重復工作。
Python為我們提供了語法糖來完成這類的tedious work。
方法就是:
query_count_proxy def query_count(name,age): return'name is%s,age is%d'%(name,age) query_count=query_count_proxy(query_count)就等同于在定義query_count函數的時候,在其前面加上query_count_proxy。
Python看到這樣的語法,就會自動的執行query_count=query_count_proxy(query_count)進行name rebinding
補充
以上就是Python實現可調用對象裝飾的核心。
可調用對象包括函數、方法、實現了__call__方法的類,上述內容只是針對函數來解釋,對于方法、實現了__call__方法的類,其基本原理相同,具體實現略有差別。
以上就是小編為大家總結的,希望可以給各位讀者帶來幫助。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/128314.html
摘要:在中,我們可以用多種方法來實現單例模式使用模塊使用使用裝飾器使用元類使用模塊其實,的模塊就是天然的單例模式,因為模塊在第一次導入時,會生成文件,當第二次導入時,就會直接加載文件,而不會再次執行模塊代碼。 單例模式 單例模式(Singleton Pattern)是一種常用的軟件設計模式,該模式的主要目的是確保某一個類只有一個實例存在。當你希望在整個系統中,某個類只能出現一個實例時,單例對...
摘要:一般情況下,我們使用裝飾器提供的語法糖,來簡化上面的寫法像上面的情況,可以動態修改函數或類功能的函數就是裝飾器。本文標題為會打扮的裝飾器本文鏈接為參考資料修飾器的函數式編程中的裝飾器介紹思誠之道裝飾器入門與提高賴明星 裝飾器 我們知道,在 Python 中,我們可以像使用變量一樣使用函數: 函數可以被賦值給其他變量 函數可以被刪除 可以在函數里面再定義函數 函數可以作為參數傳遞給另外...
一、前提概念 Python中的函數是對象。也因此,函數可以被當做變量使用。 二、代碼模型 以下代碼片段來自于: http://www.sharejs.com/codes/python/8361 # -*- coding: utf-8 -*- from threading import Thread import time class TimeoutEx...
摘要:希望引以為戒鄭傳裝飾模式如果你了解,你肯定聽過裝飾器模式。在面向對象中,裝飾模式指動態地給一個對象添加一些額外的職責。就增加一些功能來說,裝飾模式比生成子類更為靈活。 漫談 如果作為一個Python入門,不了解Python裝飾器也沒什么,但是如果作為一個中級Python開發人員,如果再不對python裝飾器熟稔于心的話,那么可能并沒有量變積累到質變。 我以前也看過很多講python 裝...
摘要:使用類裝飾器,優點是靈活性大,高內聚,封裝性。不過不用擔心,有,本身也是一個裝飾器,它的作用就是把原函數的元信息拷貝到裝飾器函數中,使得裝飾器函數也有和原函數一樣的元信息。 showImg(https://segmentfault.com/img/bVbrFWb?w=742&h=484);Python的裝飾器(decorator)是一個很棒的機制,也是熟練運用Python的必殺技之一。...
閱讀 911·2023-01-14 11:38
閱讀 878·2023-01-14 11:04
閱讀 740·2023-01-14 10:48
閱讀 1983·2023-01-14 10:34
閱讀 942·2023-01-14 10:24
閱讀 819·2023-01-14 10:18
閱讀 499·2023-01-14 10:09
閱讀 572·2023-01-14 10:02