日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術(shù)文章
文章詳情頁

Python反射機(jī)制實(shí)例講解

瀏覽:24日期:2022-08-06 17:20:35
目錄1. 反射的四個(gè)函數(shù)2. 類的反射操作3. 當(dāng)前模塊的反射操作4. 其他模塊反射操作5. 反射應(yīng)用場景之一6. 反射應(yīng)用場景之二7. 總結(jié)

通常,我們操作對(duì)象的屬性或者方法時(shí),是通過點(diǎn)“.”操作符進(jìn)行的。例如下面的代碼:

class Person: type = 'mammal' def __init__(self, name):self.name = name def say_hi(self):print(’Hello, my name is’, self.name) @staticmethod def feed():print('Three times per day.') @classmethod def sleep(cls):print('8 hours!')p = Person(’Chunming’)p.say_hi()print(p.name)

上面代碼的輸出是

Hello, my name is NikhilNikhil

反射是另外一種操作對(duì)象屬性和方法的手段,例如:

func = getattr(p, ’say_hi’) func()print(getattr(p, 'name'))

上面這段代碼的輸出是:

Hello, my name is NikhilNikhil

可見與通過點(diǎn)操作符的結(jié)果一致。

1. 反射的四個(gè)函數(shù)

getattr是獲取對(duì)象屬性或方法的函數(shù),Python的官方文檔是這樣描述其用法的:

getattr(object, name, value)

返回對(duì)象命名屬性的值。name必須是字符串。如果該字符串是對(duì)象的屬性之一,則返回該屬性的值。例如, getattr(x, ‘foobar’)等同于 x.foobar。如果指定的屬性不存在,且提供了 default值,則返回它,否則觸發(fā) AttributeError。

根據(jù)文檔理解上述代碼,getattr(p, ‘say_hi’) 獲取了p對(duì)象的say_hi屬性值并賦值給func變量,因?yàn)閟ay_hi屬性在Person類中是一個(gè)方法,要想調(diào)用這個(gè)方法, 需要執(zhí)行func(),getattr(p, “name”) 則是獲取p對(duì)象的name屬性。

除了獲取對(duì)象屬性和方法的getattr函數(shù),python還內(nèi)置了判斷、設(shè)置、刪除對(duì)象屬性和方法的函數(shù),來看看Python官方文檔對(duì)這三個(gè)函數(shù)的說明:

setattr(object, name, value)

此函數(shù)與 getattr() 兩相對(duì)應(yīng)。其參數(shù)為一個(gè)對(duì)象、一個(gè)字符串和一個(gè)任意值。字符串指定一個(gè)現(xiàn)有屬性或者新增屬性。函數(shù)會(huì)將值賦給該屬性,只要對(duì)象允許這種操作。例如,setattr(x, ‘foobar’, 123) 等價(jià)于 x.foobar = 123。

hasattr(object, name)

該實(shí)參是一個(gè)對(duì)象和一個(gè)字符串。如果字符串是對(duì)象的屬性之一的名稱,則返回 True,否則返回 False。(此功能是通過調(diào)用 getattr(object, name) 看是否有 AttributeError 異常來實(shí)現(xiàn)的。)

delattr(object, name)

setattr() 相關(guān)的函數(shù)。實(shí)參是一個(gè)對(duì)象和一個(gè)字符串。該字符串必須是對(duì)象的某個(gè)屬性。如果對(duì)象允許,該函數(shù)將刪除指定的屬性。例如 delattr(x, ‘foobar’) 等價(jià)于 del x.foobar 。

Python中通過getattr、setattr、hasattr和delattr四個(gè)函數(shù)操作屬性的機(jī)制就是反射。是通過字符串的形式操作對(duì)象屬性和方法的機(jī)制。下面對(duì)p屬性應(yīng)用setattr、hasattr和delattr這三個(gè)函數(shù)看看效果:

判斷p對(duì)象是否有say_bye屬性和say_hi屬性:

print(hasattr(p, ’say_bye’)) # 輸出Falseprint(hasattr(p, ’say_hi’)) # 輸出True

給p對(duì)象增加say_bye的方法和age屬性:

setattr(p, ’say_bye’, say_bye)setattr(p, ’age’, 18)

現(xiàn)在可以訪問這兩個(gè)屬性了,通過反射訪問:

bye = getattr(p, ’say_bye’)bye()print(getattr(p, ’age’))

或者通過點(diǎn)操作符訪問:

p.say_bye()print(p.age)

刪除age屬性:

delattr(p, ’age’)print(hasattr(p, ’age’)) # 輸出False2. 類的反射操作

除了對(duì)象的反射操作,還有類的反射操作,當(dāng)前模塊的反射操作,還有其他模塊的反射操作,其他包的反射操作。

類的反射操作,指的是對(duì)類屬性、類方法或者靜態(tài)方法執(zhí)行反射操作。

獲取類屬性:

t = getattr(Person, ’type’)print(t) # 輸出mammalf = getattr(Person, ’feed’)f() # 輸出Three times per day.s = getattr(Person, ’sleep’)s() # 8 hours!

判斷類屬性是否存在:

print(hasattr(Person, ’type’)) # 輸出Trueprint(hasattr(Person, ’name’)) # 輸出Falseprint(hasattr(Person, ’say_hi’)) # 輸出Trueprint(hasattr(Person, ’sleep’)) # 輸出Trueprint(hasattr(Person, ’feed’)) # 輸出True

此外,還可以對(duì)類添加和刪除屬性和方法。

print(delattr(Person, ’feed’))print(hasattr(Person, ’feed’))setattr(Person, ’feed’, lambda x: print('Three times per day.'))print(hasattr(Person, ’feed’))3. 當(dāng)前模塊的反射操作

當(dāng)前模塊也就是當(dāng)前代碼所在的py文件,反射也可以對(duì)當(dāng)前模塊中的變量和函數(shù)進(jìn)行操作。例如某個(gè)模塊包含一個(gè)al函數(shù),用來判斷迭代對(duì)象中每個(gè)元素是否都是True,內(nèi)容如下:

import sysdef al(iterable): for element in iterable:if not element: return False return Truethis_module = sys.modules[__name__]if hasattr(this_module, ’al’): all_true = getattr(this_module, ’al’) result = all_true([1, 2, 3, 4, True, 0]) print(result)

通過sys.modules[name]方法獲取當(dāng)前模塊的名稱。getattr第一個(gè)參數(shù)是模塊名稱,第二個(gè)參數(shù)是想要從模塊中獲取的屬性。

4. 其他模塊反射操作

對(duì)import進(jìn)來的其他模塊中的函數(shù)、屬性、變量進(jìn)行反射操作。例如,我們導(dǎo)入Python的heapq模塊,這塊模塊提供了堆隊(duì)列算法的實(shí)現(xiàn),也稱為優(yōu)先隊(duì)列算法。下面的代碼是一個(gè)實(shí)現(xiàn)堆排序的函數(shù)。

import heapqh = [(5, ’write code’), (7, ’release product’), (1, ’write spec’), (3, ’create tests’)]if hasattr(heapq, ’heapify’): heapi = getattr(heapq, ’heapify’) # 獲取heapify屬性 heapi(h) # 建堆 if hasattr(heapq, ’heappop’): heapp = getattr(heapq, ’heappop’) # 獲取heappop屬性 print([heapp(h) for _ in range(len(h))]) # 彈出并從返回堆中最小的項(xiàng)

這里,我們并沒有通過heapq.heapify和heapq.heappop方式調(diào)用heapq模塊中的函數(shù)。而是通過反射達(dá)到的同樣的效果。

5. 反射應(yīng)用場景之一

了解了反射中四個(gè)函數(shù)的基本用法。那么反射到底有什么用呢?它的應(yīng)用場景是什么呢?答案是,當(dāng)不確定所需要的屬性和函數(shù)是否存在時(shí),可以使用反射。另外一個(gè)重要作用是,可以提高代碼的擴(kuò)展性和可維護(hù)性。

假如我們把所有的加密算法都放到一個(gè)叫做encryption的模塊中維護(hù) ,并且允許使用這個(gè)模塊的用戶添加更多的加密算法到這個(gè)模塊中。encryption的模塊內(nèi)容如下:

import hashlibimport osimport sysdef md5(content=None): '''生成字符串的SHA256值''' if content is None:return ’’ md5_gen = hashlib.md5() md5_gen.update(content.encode(’utf-8’)) md5code = md5_gen.hexdigest() return md5codedef sha256(content=None): '''生成字符串的SHA256值''' if content is None:return ’’ sha256_gen = hashlib.sha256() sha256_gen.update(content.encode(’utf-8’)) sha256code = sha256_gen.hexdigest() return sha256codedef sha256_file(filename): '''生成文件的SHA256值''' if not os.path.isfile(filename):return '' sha256gen = hashlib.sha256() size = os.path.getsize(filename) # 獲取文件大小,單位是Byte with open(filename, ’rb’) as fd: # 以二進(jìn)制方式讀取文件while size >= 1024 * 1024: # 當(dāng)文件大于1MB時(shí)分塊讀取文件內(nèi)容 sha256gen.update(fd.read(1024 * 1024)) size -= 1024 * 1024sha256gen.update(fd.read()) sha256code = sha256gen.hexdigest() return sha256codedef md5_file(filename): '''生成文件的MD5值''' if not os.path.isfile(filename):return '' md5gen = hashlib.md5() size = os.path.getsize(filename) # 獲取文件大小,單位是Byte with open(filename, ’rb’) as fd:while size >= 1024 * 1024: # 當(dāng)文件大于1MB時(shí)分塊讀取文件內(nèi)容 md5gen.update(fd.read(1024 * 1024)) size -= 1024 * 1024md5gen.update(fd.read()) md5code = md5gen.hexdigest() return md5codedef encrypt_something(something, algorithm): ''' 通用加密算法 :param something: 待加密的內(nèi)容,字符串或者文件 :param algorithm: 加密算法 :return: 加密后的內(nèi)容 ''' result = '' if algorithm == 'md5':result = md5(something) elif algorithm == 'sh256':result = sha256(something) elif algorithm == 'sh256_file':result = sha256_file(something) elif algorithm == 'md5_file':result = md5_file(something) return result

其中,encrypt_something函數(shù)提供了通用加密算法,需要調(diào)用者傳入待加密的內(nèi)容和加密算法,這樣當(dāng)調(diào)用者使用encryption.py模塊時(shí),只需導(dǎo)入encrypt_something函數(shù)即可。就像這樣:

import encryptionprint(encryption.encrypt_something('learn_python_by_coding', 'sh256'))print(encryption.encrypt_something('learn_python_by_coding', 'md5'))

通過分析encrypt_something函數(shù)發(fā)現(xiàn),當(dāng)我們?cè)趀ncryption.py模塊添加更多的加密算法后,就要修改encrypt_something函數(shù),在其中增加新的if分支,隨著加密算法的增加,encrypt_something函數(shù)的分支會(huì)越來越多。

學(xué)了反射之后,encrypt_something代碼部分就可以這樣寫:

def encrypt_something(something, algorithm): ''' 通用加密算法 :param something: 待加密的內(nèi)容,字符串或者文件 :param algorithm: 加密算法 :return: 加密后的內(nèi)容 ''' this_module = sys.modules[__name__] if hasattr(this_module, algorithm):algorithm = getattr(this_module, algorithm)result = algorithm(something) else:raise ValueError('Not support {} algorithm'.format(algorithm)) return result

相比前面的采用if分支語句方式,反射更加簡潔明了,可維護(hù)性更強(qiáng),要想增加新的加密方法,只需要在encryption.py模塊添加更多的加密算法即可,encrypt_something代碼不需要任何變更。

6. 反射應(yīng)用場景之二

再看一個(gè)基于Pytest測試框架的測試腳本中應(yīng)用反射的例子,比如conftest文件內(nèi)容如下:

# content of conftest.pyimport pytestimport smtplib@pytest.fixture(scope='module')def smtp_connection(request): server = getattr(request.module, 'smtpserver', 'smtp.gmail.com') smtp_connection = smtplib.SMTP(server, 587, timeout=5) yield smtp_connection print('finalizing {} ({})'.format(smtp_connection, server)) smtp_connection.close()

request.module 是所有測試腳本,就是那些以_test結(jié)尾或者test_開頭的py文件。

server = getattr(request.module, 'smtpserver', 'smtp.gmail.com')

含義就是從測試腳本文件中找smtpserver屬性,如果找不到,默認(rèn)使用smtp.gmail.com作為smtpserver的值。如果測試腳本文件有這個(gè)屬性,則使用測試腳本中的值,例如下面這個(gè)測試腳本,smtpserver則會(huì)使用mail.python.org這個(gè)值:

# content of test_anothersmtp.pysmtpserver = 'mail.python.org' # will be read by smtp fixturedef test_showhelo(smtp_connection): assert 0, smtp_connection.helo()7. 總結(jié)

在很多開源框架中普遍采用,是提高可維護(hù)性和擴(kuò)展性的利器。如果工作中也涉及到框架開發(fā),反射一定會(huì)助一臂之力,,希望大家以后多多支持好吧啦網(wǎng)!

標(biāo)簽: Python 編程
相關(guān)文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
在线一区免费| 久久在线免费| 亚洲欧美久久精品| 久久精品欧美一区| 韩国久久久久久| 亚洲成人不卡| 欧美在线亚洲综合一区| 午夜欧美精品久久久久久久| 在线一区免费| 少妇精品在线| 欧美激情日韩| 日韩精品一卡| 国产精品普通话对白| 丝袜国产日韩另类美女| 首页亚洲欧美制服丝腿| 日韩精品国产精品| 国产精品蜜月aⅴ在线| 欧美国产美女| 91麻豆国产自产在线观看亚洲| 欧美a在线观看| 国产一区二区三区精品在线观看| 日韩欧美字幕| 国产毛片久久| 久久精品国产亚洲aⅴ| 另类中文字幕国产精品| 国产亚洲综合精品| 欧美一区91| 久久国产电影| 国产精品一区二区av日韩在线| 日韩欧美不卡| 欧美日韩网址| 午夜久久免费观看| 麻豆国产91在线播放| 日韩中文在线播放| 日韩av在线播放中文字幕| 成人羞羞视频在线看网址| 无码日韩精品一区二区免费| 日韩久久一区二区三区| 日韩欧美久久| 久久久久亚洲| 国产九九精品| 久久性天堂网| 亚洲天堂成人| 精品三级国产| 一区二区三区国产在线| 欧洲亚洲一区二区三区| 久久av资源| 蜜臀久久久99精品久久久久久| 国产欧美日韩一区二区三区四区 | 日韩精品一卡二卡三卡四卡无卡| 激情不卡一区二区三区视频在线| 蜜臀av国产精品久久久久| 欧美成a人国产精品高清乱码在线观看片在线观看久 | 久久av导航| 青青草91久久久久久久久| 日韩精品一卡二卡三卡四卡无卡| 久久精品导航| 亚洲精品**中文毛片| 国产欧美日本| 国产剧情一区二区在线观看| 天堂va在线高清一区| 日韩亚洲精品在线观看| 国产精品毛片在线看| 99成人在线| 亚欧成人精品| 日本精品另类| 日韩一区精品视频| 在线观看亚洲精品福利片| 国产精品丝袜xxxxxxx| 免费美女久久99| 亚洲三级精品| 国产日产一区| 精品国产麻豆| 成人精品亚洲| 亚洲专区在线| 国产伦理一区| 日韩黄色大片| 国产农村妇女精品一二区| 免费黄网站欧美| 日韩精品欧美成人高清一区二区| 欧美日韩91| 国产欧美日本| 色婷婷精品视频| 日韩一区二区三区高清在线观看| 久久av日韩| 亚洲调教视频在线观看| 天堂av一区| 久久精品国产68国产精品亚洲| 美国三级日本三级久久99| 男女男精品网站| 蜜桃久久久久久久| 精品三级在线| 六月婷婷一区| 国产在线看片免费视频在线观看| 亚洲中午字幕| 精品国产亚洲日本| 亚洲a一区二区三区| 国产日韩欧美在线播放不卡| 日韩欧美三级| 国产精品日本一区二区不卡视频| 国产一区二区精品久| 鲁大师成人一区二区三区| 久久在线91| 日韩欧美中文在线观看| 99成人超碰| 中文字幕在线看片| 国产欧美日韩一级| 一本综合精品| 午夜久久久久| 日韩三区免费| 国产成人精品亚洲线观看| 国产精品毛片在线看| 亚洲精品**中文毛片| 国产欧美高清| 日韩毛片一区| 免费中文字幕日韩欧美| 极品裸体白嫩激情啪啪国产精品| 欧美国产极品| 久久国产乱子精品免费女| 亚洲aa在线| 亚洲开心激情| 亚洲丝袜美腿一区| 99re国产精品| 亚洲一区欧美二区| 免费成人网www| 久久国产精品成人免费观看的软件| 国产欧美88| 欧美成人精品一级| 高清一区二区| 天堂√8在线中文| 国产精品麻豆久久| 日韩欧美精品综合| 99久久夜色精品国产亚洲1000部| 播放一区二区| 黄色不卡一区| 日韩精品一级二级 | 日本免费一区二区视频| 日本不卡视频一二三区| 免费不卡在线视频| 日韩成人午夜精品| 欧美日韩va| 福利在线一区| 黄色免费成人| 欧美在线日韩| av高清不卡| 夜久久久久久| 国产精品手机在线播放| 中文字幕在线视频网站| 国产精品毛片一区二区三区| 日本欧美一区二区在线观看| 国产精品1区| 激情婷婷亚洲| 国产欧美日韩| 99成人在线视频| 日韩和欧美的一区| 久久国产日本精品| 久久精品99国产精品日本| 国产精品专区免费| 日本亚洲视频| 日韩精品一区二区三区免费观影 | 激情欧美丁香| av不卡免费看| 精品国产成人| 天堂成人免费av电影一区| 精品国产中文字幕第一页| 亚洲一级在线| 日韩影院二区| 久久av免费| 日韩欧美中文字幕一区二区三区| 成人福利视频| 国产欧美69| 日韩欧美中文字幕在线视频| 久久精品av| 欧美好骚综合网| 免费亚洲婷婷| 国产日韩视频| 亚洲尤物在线| japanese国产精品| 日韩成人高清| 九九久久国产| 久久字幕精品一区| 欧美国产视频| 国产精品成人3p一区二区三区| 欧美专区在线| 久久xxxx| 爽好多水快深点欧美视频| 米奇777超碰欧美日韩亚洲| 国产成人免费| 色婷婷色综合| 99视频精品视频高清免费| 日韩欧美三级| 水蜜桃久久夜色精品一区| 国产一区丝袜| 在线人成日本视频| 丝袜美腿诱惑一区二区三区| 四季av一区二区凹凸精品| 樱桃视频成人在线观看| 亚洲女同av| 亚洲少妇在线| 亚州国产精品|