python裝飾器學習

來源:互聯網
上載者:User

標籤:不能   stat   rev   指令碼語言   好的   調用   this   print   icm   

python 裝飾器

裝飾器本質上是一個Python函數,它可以讓其他函數在不需要做任何代碼變動的前提下增加額外功能,裝飾器的傳回值也是一個函數對象。它經常用於有切面需求的情境,比如:插入日誌、效能測試、交易處理、緩衝、許可權校正等情境。裝飾器是解決這類問題的絕佳設計,有了裝飾器,我們就可以抽離出大量與函數功能本身無關的雷同代碼並繼續重用。

寫一個簡單的裝飾器
def deco(f):    def wrapped(*args, **kwargs):        print "start"        f(*args, **kwargs)        print "end"    return wrapped@decodef func(a):    print afunc("func run")

運行代碼最終得到:

startfunc runend

通過範例程式碼可以更好的理解裝飾器的定義。

帶參數的裝飾器
def deco(level):    def wrapped(f):        def wrapper_inner(*args, **kwargs):            print "%s start" % level            f(*args, **kwargs)            print "end"        return wrapper_inner    return wrapped@deco("i am info")def func(a):    print afunc("func run")

如裝飾器定義中的使用,在列印日誌時,我們可能需要輸入不同的等級。
從這裡也可以看出裝飾器的參數傳入順序,從上到下,裝飾器參數,裝飾器修飾函數,和函數參數

內建裝飾器

內建裝飾器與普通裝飾器原理上不同,返回的是一個類對象,

@property
class TestEntiy(object):    def __init__(self):        super(TestEntiy, self).__init__()        self._position = 5    @property    def position(self):        return self._position    @position.setter    def position(self, value):        self._position = value            @position.deleter    def position(self):        del self._position

使用@文法糖,更簡潔的實現get和set
但是要注意的是setter和deleter是property的第二三個參數,不能直接使用@文法,而應該使用已有的peoperty對象調用

@staticmethod和@classmethod

分別返回staticmethod和classmethod對象,來調用修飾函數,實現只能使用類調用而非對象調用

基於裝飾器實現event回調語義

在完成遊戲作業使用unity做用戶端,python做服務端。由於unity使用的指令碼語言是c#,因此在完成資料同步時,對於伺服器的資料進行分發時,使用了delegate & event語義來實現event回調,解決了資料管理實體與socket網路服務實體代碼之間的緊耦合。但是後來換了用戶端引擎之後使用python開發用戶端,為了實現event回調語義來解決服務端資料分發至各個資料管理實體,對於python語言的裝飾器文法糖進行了學習

def msg_listener(*events):    def wrapper(func):        func.events = events        return func    return wrapper

首先是裝飾器,對於被裝飾函數對象加上events屬性,這裡python很騷的地方,everything is object
然後我們再來看給每個函數加上的events是個什麼東西

class MsgNotifierEvent(object):    _events = []    def __init__(self, name):        super(MsgNotifierEvent, self).__init__()        self._name = name        self._callback = []        MsgNotifierEvent._events.append(self)    def __iadd__(self, callback):        self._callback.append(callback)        return self    def __call__(self, *args, **kwargs):        for cb in self._callback:            try:                cb(*args, **kwargs)            except Exception as e:                print "msgNotifier callback error, function:", cb.__name__, e    @classmethod    def clear(cls, name):        for event in cls._events:            if event._name == name:                event._callback = []                break

這裡從寫了__call__函數,因此主要的使用實在調用此對象時,那麼_callback裡面又是什麼呢?
以下是我用戶端資料管理的基類,主要是包含資料監聽的邏輯(Event回調),這裡可以看到init_data_listener函數擷取了所有包含events屬性的函數,將這些函數的都加到對應events的回調隊列中(這裡可以看上一段代碼對於__iadd__的重載),這樣就完整實現了通過監聽器MsgNotifierEvent的調用,實現了資料到來之後對於資料處理函數的回調

# -*- coding: utf-8 -*-import abcimport inspectclass ManagerBase(object):    #包含資料接受的實體基類,需自己實現destroy函數,清除監聽器和事件    __metaclass__ = abc.ABCMeta    def __init__(self):        super(ManagerBase, self).__init__()        self.init_data_listener()    def init_data_listener(self):        for listener_name, listener in inspect.getmembers(self, lambda f: hasattr(f, ‘events‘)):            for event in listener.events:                event += listener    @abc.abstractmethod    def destroy(self):        raise NotImplementedError

以下為測試代碼

class TestEntiy(ManagerBase):    def __init__(self):        super(TestEntiy, self).__init__()    @msg_listener(game_msg_recv)    def update(self, protocol):        print "this is deal data:", protocol    def destroy(self):        MsgNotifierEvent.clear("game_msg_recv")        test = TestEntiy()game_msg_recv("i am test1")test.destroy()game_msg_recv("i am test2")#輸出#this is deal data: i am test1

python裝飾器學習

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.