激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

腳本之家,腳本語言編程技術及教程分享平臺!
分類導航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服務器之家 - 腳本之家 - Python - Python中的多重裝飾器

Python中的多重裝飾器

2020-06-03 10:06腳本之家 Python

這篇文章主要介紹了Python中的多重裝飾器,多重裝飾器即多個裝飾器修飾同一個對象,但實際上并非完全如此,本文用實例講解了各種情況,需要的朋友可以參考下

多重裝飾器,即多個裝飾器修飾同一個對象【實際上并非完全如此,且看下文詳解】

1.裝飾器無參數:

復制代碼 代碼如下:


>>> def first(func):
    print '%s() was post to first()'%func.func_name
    def _first(*args,**kw):
        print 'Call the function %s() in _first().'%func.func_name
        return func(*args,**kw)
    return _first

 


>>> def second(func):
    print '%s() was post to second()'%func.func_name
    def _second(*args,**kw):
        print 'Call the function %s() in _second().'%func.func_name
        return func(*args,**kw)
    return _second


>>> @first
@second
def test():return 'hello world'

test() was post to second()
_second() was post to first()
>>> test()
Call the function _second() in _first().
Call the function test() in _second().
'hello world'
>>>

 

實際上它是相當于下面的代碼:

復制代碼 代碼如下:


>>> def test():
    return 'hello world'

 

>>> test=second(test)
test() was post to second()
>>> test
<function _second at 0x000000000316D3C8>
>>> test=first(test)
_second() was post to first()
>>> test
<function _first at 0x000000000316D358>
>>> test()
Call the function _second() in _first().
Call the function test() in _second().
'hello world'
>>>


2.裝飾器有參數:

復制代碼 代碼如下:


>>> def first(printResult=False):
    def _first(func):
        print '%s() was post to _first()'%func.func_name
        def __first(*args,**kw):
            print 'Call the function %s() in __first().'%\
                  func.func_name
            if printResult:
                print func(*args,**kw),'#print in __first().'
            else:
                return func(*args,**kw)
        return __first
    return _first

 

>>> def second(printResult=False):
    def _second(func):
        print '%s() was post to _second()'%func.func_name
        def __second(*args,**kw):
            print 'Call the function %s() in __second().'%\
                  func.func_name
            if printResult:
                print func(*args,**kw),'#print in __second().'
            else:
                return func(*args,**kw)
        return __second
    return _second

>>> @first(True)
@second(True)
def test():
    return 'hello world'

test() was post to _second()
__second() was post to _first()
>>> test()
Call the function __second() in __first().
Call the function test() in __second().
hello world #print in __second().
None #print in __first().
>>>

 

如上,第35行輸出后調用__second(),而__second()中又調用了test()并print test(),而后返回__first()中繼續執行print,而這個print語句print的內容是__second()返回的None

它等同于:

 

復制代碼 代碼如下:


>>> def test():
    return 'hello world'

 

>>> test=second(True)(test)
test() was post to _second()
>>>
>>> test
<function __second at 0x000000000316D2E8>
>>> test=first(True)(test)
__second() was post to _first()
>>> test
<function __first at 0x0000000003344C18>
>>>


3.多重裝飾器的應用:

 

比如你是項目經理,你要求每一個代碼塊都必須有參數檢查ArgsType和責任檢查ResponsibilityRegister,這樣就需要兩個裝飾器對此代碼塊進行監督。

復制代碼 代碼如下:


#coding=utf-8
import os,sys,re
from collections import OrderedDict

 

def ArgsType(*argTypes,**kwTypes):
    u'''ArgsType(*argTypes,**kwTypes)
    options=[('opt_UseTypeOfDefaultValue',False)]

    以下為本函數相關的開關,并非類型檢驗相關的關鍵字參數,所有options:
    opt_UseTypeOfDefaultValue=>bool:False,為True時,將對沒有指定類型的帶默
                               認值的參數使用其默認值的類型
    '''
    def _ArgsType(func):
        #確定所有的parameter name
        argNames=func.func_code.co_varnames[:func.func_code.co_argcount]
        #確定所有的default parameter
        defaults=func.func_defaults
        if defaults:
            defaults=dict(zip(argNames[-len(defaults):],defaults))
        else:defaults=None
        #將“參數類型關鍵字參數”中的所有“options關鍵字參數”提出
        options=dict()
        for option,default in [('opt_UseTypeOfDefaultValue',False)]:
            options[option]=kwTypes.pop(option,default)
        #argTypes和kwTypes的總長度應該與argNames一致
        if len(argTypes)+len(kwTypes)>len(argNames):
            raise Exception('Too much types to check %s().'%func.func_name)
        #所有kwTypes中的鍵不能覆蓋在argTypes中已經占用的names
        if not set(argNames[len(argTypes):]).issuperset(
            set(kwTypes.keys())):
            raise Exception('There is some key in kwTypes '+
                'which is not in argNames.')
        #確定所有的參數應該有的types
        types=OrderedDict()
        for name in argNames:types[name]=None
        if len(argTypes):
            for i in range(len(argTypes)):
                name=argNames[i]
                types[name]=argTypes[i]
        else:
            for name,t in kwTypes.items():
                types[name]=t
        if len(kwTypes):
            for name,t in kwTypes.items():
                types[name]=t
        #關于default parameter的type
        if options['opt_UseTypeOfDefaultValue']:
            for k,v in defaults.items():
                #如果default parameter的type沒有另外指定,那么就使用
                #default parameter的default value的type
                if types[k]==None:
                    types[k]=type(v)
        def __ArgsType(*args,**kw):
            #order the args
            Args=OrderedDict()
            #init keys
            for name in argNames:Args[name]=None
            #init default values
            if defaults is not None:
                for k,v in defaults.items():
                    Args[k]=v
            #fill in all args
            for i in range(len(args)):
                Args[argNames[i]]=args[i]
            #fill in all keyword args
            for k,v in kw.items():
                Args[k]=v
            #check if there is some None in the values
            if defaults==None:
                for k in Args:
                    if Args[k]==None:
                        if defaults==None:
                            raise Exception(('%s() needs %r parameter, '+
                                'which was not given')%(func.func_name,k))
                        else:
                           if not defaults.has_key(k):
                                raise Exception(('Parameter %r of %s() is'+
                                    ' not a default parameter')%\
                                    (k,func.func_name))
            #check all types
            for k in Args:
                if not isinstance(Args[k],types[k]):
                    raise TypeError(('Parameter %r of %s() must be '+
                        'a %r object, but you post: %r')%\
                        (k,func.func_name,types[k],Args[k]))
            return func(*args,**kw)
        return __ArgsType
    return _ArgsType

def ResponsibilityRegister(author):
    def _ResponsibilityRegister(func):
        def __ResponsibilityRegister(*args,**kw):
            try:
                return func(*args,**kw)
            except Exception as e:
                print ("Something is wrong, It's %s's responsibility."%\
                       author).center(80,'*')
                raise e
        return __ResponsibilityRegister
    return _ResponsibilityRegister

@ResponsibilityRegister('Kate')
@ArgsType(str,int)
def left(Str,Len=1):
    return Str[:Len]

print 'Good calling:'
print left('hello world',8)
print 'Bad calling:'
print left(3,7)

 

這里沒有文檔,所以調用者不知道,使用了錯誤的調用,導致出錯,這是Kate的責任。

像上面這種,對代碼有兩種互不相干的檢驗時,就可以使用多重裝飾器。

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 91重口视频 | 亚洲一区二区 | 性欧美一区二区 | 久久经典国产视频 | 97超级碰碰人国产在线观看 | 视频久久免费 | 婷婷亚洲一区二区三区 | 杏美月av | 国产乱淫a∨片免费视频 | 九九热视频这里只有精品 | 黄色免费小视频网站 | 亚洲精品永久视频 | 免费视频xxxx| 久久精品亚洲精品国产欧美kt∨ | 欧美日韩在线中文 | 55夜色66夜色国产精品视频 | 欧美亚洲啪啪 | 欧美日韩在线看片 | 国产一区精品视频 | 日韩精品羞羞答答 | 精品亚洲va在线va天堂资源站 | 久色乳综合思思在线视频 | 永久免费av在线 | 天天夜天天操 | 国产精品一区二区三区在线看 | av人人| 欧美黄色大片免费观看 | 久久精品污 | 国产一区免费观看 | 草b视频在线观看 | 91色琪琪电影亚洲精品久久 | 欧美在线观看视频网站 | 亚洲精品永久视频 | 国产成年人在线观看 | 麻豆视频在线播放 | 99re久久最新地址获取 | 国产乱淫a∨片免费观看 | 日本在线视频二区 | 日韩一级免费毛片 | 久久99精品久久 | 亚洲午夜免费电影 |