国产性生交xxxxx免费-国产中文字幕-啊灬啊灬啊灬快灬高潮了,亚洲国产午夜精品理论片在线播放 ,亚洲欧洲日本无在线码,色爽交视频免费观看

鍋爐信息網 > 鍋爐知識 > 鍋爐百科

工廠函數

發布時間:

普通工廠函數的實現def recoder(strname, age):n    print('name:', strname, 'age:', age)nndef cuifun(age):

普通工廠函數的實現

def recoder(strname, age):n print('name:', strname, 'age:', age)nndef cuifun(age): # 工廠函數n strname='cui'n return recoder(strname,age)nncuifun(24) # name: cui age: 24

工廠函數cuifun封裝了recoder,但是這樣寫很麻煩,每換一個strname都要寫不同的函數

閉合函數(closure)

def wrapperfun(strname): # 閉合函數,strname為自由變量n def recoder(age):n print("name:", strname, 'age:', age)n return recodernnfun = wrapperfun('cui') # fun是recoder的閉合函數nfun(24) # name: cui age: 24nnfun2 = wrapperfun('ma')nfun2(25) # name: ma age: 25nn# __closure__屬性記錄自由變量的參數對象地址(tuple),當閉合函數被調用時,會根據該地址找到自由變量nprint(fun.__closure__) # (<cell at 0x00000153E6C59A98: str object at 0x00000153E6D7C8F0>,)

實現裝飾器

在wrapperfun函數上增加參數校驗的功能:

def checkParam(fn): # 裝飾器函數n def wrapper(strname):n if isinstance(strname, (str)):n return fn(strname)n print("variable strname is not a string type")n returnnn return wrappernnndef wrapperfun(strname):n def recoder(age):n print('name:', strname, 'age:', age)nn return recodernnnwrapperfun2 = checkParam(wrapperfun)nfun = wrapperfun2('cui')nfun(24) # name: cui age: 24nfun = wrapperfun2(37) # variable strname is not a string type

checkParam是一個裝飾器函數,返回值是內部定義的wrapper函數。為了實現對原有函數wrapperfun的參數檢查,將wrapper函數的參數和wrapperfun的參數保持一致。若被檢查的參數合法,再調用原有函數,并將參數傳進去;若不合法,則打印警告。

在使用時,直接將wrapperfun傳入checkParam中,來完成對原函數wrapperfun的裝飾,并得到帶有參數檢查的閉合函數wrapperfun2。

裝飾器本質是一個閉合函數,該閉合函數的自由變量是一個函數。

@修飾符

def checkParam(fn):n def wrapper(strname):n if isinstance(strname, (str)):n return fn(strname)n print("variable strname is not a string type")n returnnn return wrappernn@checkParamndef wrapperfun(strname):n def recoder(age):n print('name:', strname, 'age:', age)nn return recodernnfun = wrapperfun('cui')nfun(24) # name: cui age: 24nnfun = wrapperfun(37) # variable strname is not a string type

能夠接收任何參數的通用參數修飾器

之前的裝飾器checkParam內部實現了一個wrapper函數,wrapper函數的參數與被裝飾函數參數一樣,這樣才能實現對被裝飾函數的參數檢查,并將輸入參數傳給裝飾函數。

為了在定義裝飾器時解耦內部wrapper的參數對被裝飾函數的強依賴關系,可以使用能夠適應任何參數的通用參數裝飾器

def checkParam(fn): # 裝飾器n def wrapper(*args, **kwargs):n if isinstance(args[0], (str)): # 對fn的第一個參數的類型進行檢查n return fn(*args, **kwargs)n print("variable strname is not a string type")n returnnn return wrapper

可接收參數的通用修飾器

def isadmin(userid):n def checkParam(fn):n def wrapper(*args, **kwargs):n if userid != 'admin':n print('Operation is prohibited as you are not admin!')n returnn if isinstance(args[0], (str)):n return fn(*args, **kwargs)n print("variable strname is not a string type")n returnnn return wrappern return checkParamnn@isadmin(userid='admin')ndef wrapperfun(strname):n def recoder(age):n print('name:', strname, 'age:', age)nn return recodernn@isadmin(userid='user')ndef wrapperfun2(strname):n def recoder(age):n print('name:', strname, 'age:', age)nn return recodernnnfun = wrapperfun('cui') # 此時的fun是strname初始化后的recoder nfun(24) # name: cui age: 24nnfun2 = wrapperfun(37) # variable strname is not a string typenfun3 = wrapperfun2(37) # Operation is prohibited as you are not admin!nnn# 下面不用@寫一個普通裝飾器ndef wrapperfun3(strname):n def recoder(age):n print('name:', strname, 'age:', age)nn return recodernn# 執行isadmin(userid='user')返回一個裝飾器checkParam,n# 再調用checkParam,傳入參數wrapperfun3,返回wrapper函數nwrapperfun3 = isadmin(userid='admin')(wrapperfun3)nprint(wrapperfun3.__name__) # wrappernfun4=wrapperfun3('cui')nfun4(24)

注意:使用@修飾符使調用時節省了不少代碼,可以直接調用被修飾函數了。

裝飾器返回函數的名稱修復

def isadmin(userid):n def checkParam(fn):n def wrapper(*args, **kwargs):n if userid != 'admin':n print('Operation is prohibited as you are not admin!')n returnn if isinstance(args[0], (str)):n return fn(*args, **kwargs)n print("variable strname is not a string type")n returnn wrapper.__name__ = fn.__name__ # 修改wrapper的namen return wrappern return checkParamnnnndef wrapperfun(strname):n def recoder(age):n print('name:', strname, 'age:', age)nn return recodernnwrapperfun = isadmin(userid='admin')(wrapperfun)nprint(wrapperfun.__name__) # wrapperfun

也可以通過內置裝飾器functools.wraps來實現此功能

import functoolsndef isadmin(userid):n def checkParam(fn):n @functools.wraps(fn) # wrapper的函數名稱會變成與傳入的fn參數一樣的函數名稱n def wrapper(*args, **kwargs):n if userid != 'admin':n print('Operation is prohibited as you are not admin!')n returnn if isinstance(args[0], (str)):n return fn(*args, **kwargs)n print("variable strname is not a string type")n returnnn return wrappern return checkParamnnnndef wrapperfun(strname):n def recoder(age):n print('name:', strname, 'age:', age)nn return recodernnwrapperfun = isadmin(userid='admin')(wrapperfun)nprint(wrapperfun.__name__) # wrapperfun

組合裝飾器

def checkParam(fn):n def wrapper(*args, **kwargs):n if isinstance(args[0], (str)):n return fn(*args, **kwargs)n print("variable strname is not a string type")n returnn return wrappernndef logging(userid):n def checkParam(fn):n def wrapper(*args, **kwargs):n print(userid,end=':')n return fn(*args, **kwargs)n return wrappern return checkParamnn@logging(userid='admin')n@checkParamndef wrapperfun(strname):n def recoder(age):n print('name:',strname,'age:',age)n return recodernnfun = wrapperfun('cui')nfun(24) # admin:name: cui age: 24

使用裝飾器,可以將代碼按照要實現功能的主次逐層分開,這就是面向切面的編程思想(Aspect Oriented Program AOP)

多裝飾器的調用順序

def logging(fn):n print("in logging")n def wrapper_logging(*args, **kwargs):n print("in wrapper_logging")n return fn(*args, **kwargs)n return wrapper_loggingnndef checkParam(fn):n print("in checkParam")n def wrapper_checkParam(*args, **kwargs):n print('in wrapper_checkParam')n return fn(*args, **kwargs)n return wrapper_checkParamnn@loggingn@checkParamndef wrapperfun(strname): # 輸出:in checkParam n in loggingn print('name:',strname)nnwrapperfun('cui') # 輸出:in wrapper_logging n in wrapper_checkParam n name:cui

如果不使用@修飾器,代碼執行順序可以看的很清楚:

def wrapperfun(strname):n print('name:',strname)nnnc = checkParam(wrapperfun) # in checkParamnprint(c.__name__) # wrapper_checkParamnc2 = logging(c) # in loggingnprint(c2.__name__) # wrapper_loggingnc2('cui') # in wrapper_logging n in wrapper_checkParam n name:cui

解決‘同作用域下默認參數被覆蓋’的問題

def recoder(strname, age):n print('name:',strname,'age:',age)nndef makerecoders():n acts = []n for i in ["cui","ma"]:n acts.append(lambda age:recoder(i, age))n return actsnnfor a in (makerecoders()):n a(age=32) # name: ma age: 32 n name: ma age: 32

上面的例子中,通過for循環遍歷列表來批量生成工廠函數,但是只有列表的最后一個元素起到了默認值作用,前面的元素均沒有生效,應改為下述寫法:

def recoder(strname, age):n print('name:', strname, 'age:', age)nnndef makerecoders():n acts = []n for i in ["cui", "ma"]:n acts.append(lambda age, i=i: recoder(i, age)) # 將循環值i作為參數傳入匿名函數n return actsnnnfor a in (makerecoders()):n a(age=32) # name: cui age: 32 n name: ma age: 32

精選推薦

  • 711關東煮供應商
    711關東煮供應商

    今天給大家介紹三位,奶粉,全家、羅森這些便利店里關東煮的供應商。店里賣三四塊錢一串的關東煮,在網上買不到,一塊錢就搞定。首先關東

  • 健康日歷|高壓鍋容易爆炸的4個原因
    健康日歷|高壓鍋容易爆炸的4個原因

    來源:醫藥養生保健報設計:李雅琴醫學審核:姜峰出品人:胡麗麗

  • 高爐
    高爐

    今天這活卻是個白事,等到了時辰,那家人便準備火化,本來準備送普爐,我卻心中一動,便對那家人說道:“這老人走也不要省,還是送高爐吧。”

  • 高壓鍋和電壓力鍋的區別,推薦幾款點壓力鍋
    高壓鍋和電壓力鍋的區別,推薦幾款點壓

    記得之前有一次去朋友家玩,他正在用高壓鍋煮小米粥,是的,高壓鍋壓小米粥,大概煮了半小時,高壓鍋突然爆炸了,現場慘不忍睹啊,幸好廚房里沒

0