- 論壇徽章:
- 0
|
多重裝飾器,即多個(gè)裝飾器修飾同一個(gè)對(duì)象【實(shí)際上并非完全如此,且看下文詳解】
1.裝飾器無(wú)參數(shù):- >>> 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'
- >>>
復(fù)制代碼 實(shí)際上它是相當(dāng)于下面的代碼:- >>> 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'
- >>>
復(fù)制代碼 2.裝飾器有參數(shù):- >>> 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().
- >>>
復(fù)制代碼 如上,第35行輸出后調(diào)用__second(),而__second()中又調(diào)用了test()并print test(),而后返回__first()中繼續(xù)執(zhí)行print,而這個(gè)print語(yǔ)句print的內(nèi)容是__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>
- >>>
復(fù)制代碼 3.多重裝飾器的應(yīng)用:
比如你是項(xiàng)目經(jīng)理,你要求每一個(gè)代碼塊都必須有參數(shù)檢查ArgsType和責(zé)任檢查ResponsibilityRegister,這樣就需要兩個(gè)裝飾器對(duì)此代碼塊進(jìn)行監(jiān)督。- #coding=utf-8
- import os,sys,re
- from collections import OrderedDict
- def ArgsType(*argTypes,**kwTypes):
- u'''ArgsType(*argTypes,**kwTypes)
- options=[('opt_UseTypeOfDefaultValue',False)]
- 以下為本函數(shù)相關(guān)的開(kāi)關(guān),并非類(lèi)型檢驗(yàn)相關(guān)的關(guān)鍵字參數(shù),所有options:
- opt_UseTypeOfDefaultValue=>bool:False,為T(mén)rue時(shí),將對(duì)沒(méi)有指定類(lèi)型的帶默
- 認(rèn)值的參數(shù)使用其默認(rèn)值的類(lèi)型
- '''
- 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
- #將“參數(shù)類(lèi)型關(guān)鍵字參數(shù)”中的所有“options關(guān)鍵字參數(shù)”提出
- options=dict()
- for option,default in [('opt_UseTypeOfDefaultValue',False)]:
- options[option]=kwTypes.pop(option,default)
- #argTypes和kwTypes的總長(zhǎng)度應(yīng)該與argNames一致
- if len(argTypes)+len(kwTypes)>len(argNames):
- raise Exception('Too much types to check %s().'%func.func_name)
- #所有kwTypes中的鍵不能覆蓋在argTypes中已經(jīng)占用的names
- if not set(argNames[len(argTypes):]).issuperset(
- set(kwTypes.keys())):
- raise Exception('There is some key in kwTypes '+
- 'which is not in argNames.')
- #確定所有的參數(shù)應(yīng)該有的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
- #關(guān)于default parameter的type
- if options['opt_UseTypeOfDefaultValue']:
- for k,v in defaults.items():
- #如果default parameter的type沒(méi)有另外指定,那么就使用
- #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)
復(fù)制代碼 這里沒(méi)有文檔,所以調(diào)用者不知道,使用了錯(cuò)誤的調(diào)用,導(dǎo)致出錯(cuò),這是Kate的責(zé)任。
像上面這種,對(duì)代碼有兩種互不相干的檢驗(yàn)時(shí),就可以使用多重裝飾器。 |
|