實(shí)現(xiàn)python?namedtuple元類編程
起步
namedtuple 是 collections 模塊下的一個(gè)功能,它是類工廠函數(shù),能返回 tuple 子類,允許通過字段名向元組中取值,性能上接近于元組。
Person = namedtuple('Person', 'name age')
p = Person(name='Tony', age=18)
print(p.name) # 'Tony'
print(p.age) # 18我們來試著自己動(dòng)手來實(shí)現(xiàn)這個(gè) namedtuple 功能。因?yàn)檫@個(gè)功能需求明確,沒什么模塊依賴,通過自己的實(shí)現(xiàn)后再去看看真正在 cpython 里的源碼就會(huì)比較清晰。
需求分析
對于代碼 Person = namedtuple('Person', 'name age') 讓它等價(jià)于:
class Person(tuple):
def __new__(cls, name, age):
return tuple.__new__(cls, (name, age))
@property
def name(self):
return self[0]
@property
def age(self):
return self[1]那么有一種實(shí)現(xiàn)就是,拼湊成這樣的代碼塊字符串,再通過 exec(code) 來創(chuàng)建類,舊版本(小于 3.7)的 namedtuple 在 cpython 中還真就是這么實(shí)現(xiàn)的。
PS: 重寫了 __new__ 而不是 __init__ ,有一個(gè)原因是因?yàn)樵M一旦創(chuàng)建就不可變。為了能夠通過字段名取值,這里引入了 property 修飾符。
構(gòu)造類的字符串模板創(chuàng)建類
基于這個(gè)思路一個(gè)簡陋的就能寫了出來:
# 類名稱模板
_class_template = '''
class {typename}(tuple):
def __new__(_cls, {arg_list}):
return tuple.__new__(_cls, ({arg_list}))
{field_defs}
'''
# 屬性模板
_field_template = '''
@property
def {name}(self):
return self[{index}]
'''
def namedtuple(typename, field_names):
field_names = field_names.split()
class_definition = _class_template.format(
typename=typename,
arg_list=arg_list = repr(field_names).replace("'", "")[1:-1],
field_defs=''.join(_field_template.format(index=index, name=name)
for index, name in enumerate(field_names))
)
namespace = {}
exec(class_definition, namespace)
return namespace[typename]
# use demo
Person = namedtuple('Person', 'name age')
p = Person(name='Tony', age=18)
print(isinstance(p, tuple)) # True
print(p.name) # Tony
print(p.age) # 18cpython 中的 namedtuple 便是基于這個(gè)思路實(shí)現(xiàn)的
源碼:https://github.com/python/cpy...,這個(gè)實(shí)現(xiàn)方式一直沿用到了 3.6.x 。
直到因?yàn)樾阅茉蚨M(jìn)行了改版,PR見:https://github.com/python/cpy...
基于元類編程
改進(jìn)后的 namedtuple 更能體現(xiàn)元類編程的思想,對性能也有明顯的改善。我用簡化的代碼來展示改版后的 namedtuple 的工作內(nèi)容:
def _tuplegetter(index):
@property
def _getter(self):
return self[index]
return _getter
def namedtuple(typename, field_names):
field_names = field_names.split()
arg_list = repr(field_names).replace("'", "")[1:-1]
s = f'def __new__(_cls, {arg_list}): return tuple.__new__(_cls, ({arg_list}))'
namespace = {}
exec(s, namespace)
__new__ = namespace['__new__']
class_namespace = {'__new__': __new__}
for index, name in enumerate(field_names):
class_namespace[name] = _tuplegetter(index)
result = type(typename, (tuple,), class_namespace)
return result到此,一個(gè)簡易版的 namedtuple 就結(jié)構(gòu)就完成了,改進(jìn)后的 exec 調(diào)用中只有一行代碼,性能會(huì)更好,舊版本的還會(huì)額外 import 其他依賴。然后就是構(gòu)造元類編程中類屬性和方法了。屬性的獲取是通過寫的 _getter 來完成,而實(shí)際上源碼上會(huì)委托給 operator.itemgetter 函數(shù)。
總結(jié)
相信從本文中理解了 namedtuple 的設(shè)計(jì)和實(shí)現(xiàn)原理,再去閱讀源代碼,能更快的理解源碼,起到事半功倍的效果。
以上就是實(shí)現(xiàn)python namedtuple元類編程的詳細(xì)內(nèi)容,更多關(guān)于python namedtuple元類的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Python調(diào)用豆包API實(shí)現(xiàn)批量提取圖片信息
這篇文章主要為大家詳細(xì)介紹了Python如何通過調(diào)用豆包API實(shí)現(xiàn)批量提取圖片信息的功能,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解下2025-11-11
剖析Django中模版標(biāo)簽的解析與參數(shù)傳遞
這篇文章主要介紹了剖析Django中模版標(biāo)簽的解析與參數(shù)傳遞,Django是重多高人氣Python框架中最為著名的一個(gè),需要的朋友可以參考下2015-07-07
Python 實(shí)現(xiàn)勞拉游戲的實(shí)例代碼(四連環(huán)、重力四子棋)
這篇文章主要介紹了Python 實(shí)現(xiàn)勞拉游戲的實(shí)例代碼(四連環(huán)、重力四子棋),本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-03-03
Python如何使用內(nèi)置庫matplotlib繪制折線圖
這篇文章主要介紹了Python如何使用內(nèi)置庫matplotlib繪制折線圖,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-02-02
Python實(shí)現(xiàn)簡單的列表冒泡排序和反轉(zhuǎn)列表操作示例
這篇文章主要介紹了Python實(shí)現(xiàn)簡單的列表冒泡排序和反轉(zhuǎn)列表操作,涉及Python列表遍歷、排序、追加等相關(guān)操作技巧,需要的朋友可以參考下2019-07-07
基于Python實(shí)現(xiàn)一個(gè)簡單的學(xué)生管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了如何利用python實(shí)現(xiàn)簡單的學(xué)生信息管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-12-12
Python dict和defaultdict使用實(shí)例解析
這篇文章主要介紹了Python dict和defaultdict使用實(shí)例解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-03-03
使用Python高效獲取網(wǎng)絡(luò)數(shù)據(jù)的操作指南
網(wǎng)絡(luò)爬蟲是一種自動(dòng)化程序,用于訪問和提取網(wǎng)站上的數(shù)據(jù),Python是進(jìn)行網(wǎng)絡(luò)爬蟲開發(fā)的理想語言,擁有豐富的庫和工具,使得編寫和維護(hù)爬蟲變得簡單高效,本文將詳細(xì)介紹如何使用Python進(jìn)行網(wǎng)絡(luò)爬蟲開發(fā),包括基本概念、常用庫、數(shù)據(jù)提取方法、反爬措施應(yīng)對以及實(shí)際案例2025-03-03

