实现python namedtuple元类编程

 更新时间:2023年07月25日 16:56:26   作者:weapon  
这篇文章主要为大家介绍了实现python namedtuple元类编程,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

起步

namedtuple 是 collections 模块下的一个功能,它是类工厂函数,能返回 tuple 子类,允许通过字段名向元组中取值,性能上接近于元组。

Person = namedtuple('Person', 'name age')
p = Person(name='Tony', age=18)
print(p.name)  # 'Tony'
print(p.age)   # 18

我们来试着自己动手来实现这个 namedtuple 功能。因为这个功能需求明确,没什么模块依赖,通过自己的实现后再去看看真正在 cpython 里的源码就会比较清晰。

需求分析

对于代码 Person = namedtuple('Person', 'name age') 让它等价于:

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]

那么有一种实现就是,拼凑成这样的代码块字符串,再通过 exec(code) 来创建类,旧版本(小于 3.7)的 namedtuple 在 cpython 中还真就是这么实现的。

PS: 重写了 __new__ 而不是 __init__ ,有一个原因是因为元组一旦创建就不可变。为了能够通过字段名取值,这里引入了 property 修饰符。

构造类的字符串模板创建类

基于这个思路一个简陋的就能写了出来:

# 类名称模板
_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)                # 18

cpython 中的 namedtuple 便是基于这个思路实现的

源码:https://github.com/python/cpy...,这个实现方式一直沿用到了 3.6.x 。

直到因为性能原因而进行了改版,PR见:https://github.com/python/cpy...

基于元类编程

改进后的 namedtuple 更能体现元类编程的思想,对性能也有明显的改善。我用简化的代码来展示改版后的 namedtuple 的工作内容:

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

到此,一个简易版的 namedtuple 就结构就完成了,改进后的 exec 调用中只有一行代码,性能会更好,旧版本的还会额外 import 其他依赖。然后就是构造元类编程中类属性和方法了。属性的获取是通过写的 _getter 来完成,而实际上源码上会委托给 operator.itemgetter 函数。

总结

相信从本文中理解了 namedtuple 的设计和实现原理,再去阅读源代码,能更快的理解源码,起到事半功倍的效果。

以上就是实现python namedtuple元类编程的详细内容,更多关于python namedtuple元类的资料请关注脚本之家其它相关文章!

相关文章

  • Python中常见的数制转换有哪些

    Python中常见的数制转换有哪些

    在本篇文章里小编给大家整理的是一篇关于Python中常见的数制转换例举内容,有需要的朋友们可以跟着学习下。
    2020-05-05
  • python批量连接服务器检查容器是否正常

    python批量连接服务器检查容器是否正常

    在生产中,我们可能有很多项目或者很多环境,可能会部署在几百上千的服务器里面,我们该怎么定时去监控这些服务器里面的容器服务器是否正常呢,本文就来为大家讲解
    2024-01-01
  • Python调用豆包API实现批量提取图片信息

    Python调用豆包API实现批量提取图片信息

    这篇文章主要为大家详细介绍了Python如何通过调用豆包API实现批量提取图片信息的功能,文中的示例代码讲解详细,感兴趣的小伙伴可以了解下
    2025-11-11
  • 剖析Django中模版标签的解析与参数传递

    剖析Django中模版标签的解析与参数传递

    这篇文章主要介绍了剖析Django中模版标签的解析与参数传递,Django是重多高人气Python框架中最为著名的一个,需要的朋友可以参考下
    2015-07-07
  • Python 实现劳拉游戏的实例代码(四连环、重力四子棋)

    Python 实现劳拉游戏的实例代码(四连环、重力四子棋)

    这篇文章主要介绍了Python 实现劳拉游戏的实例代码(四连环、重力四子棋),本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-03-03
  • Python如何使用内置库matplotlib绘制折线图

    Python如何使用内置库matplotlib绘制折线图

    这篇文章主要介绍了Python如何使用内置库matplotlib绘制折线图,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-02-02
  • Python实现简单的列表冒泡排序和反转列表操作示例

    Python实现简单的列表冒泡排序和反转列表操作示例

    这篇文章主要介绍了Python实现简单的列表冒泡排序和反转列表操作,涉及Python列表遍历、排序、追加等相关操作技巧,需要的朋友可以参考下
    2019-07-07
  • 基于Python实现一个简单的学生管理系统

    基于Python实现一个简单的学生管理系统

    这篇文章主要为大家详细介绍了如何利用python实现简单的学生信息管理系统,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-12-12
  • Python dict和defaultdict使用实例解析

    Python dict和defaultdict使用实例解析

    这篇文章主要介绍了Python dict和defaultdict使用实例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-03-03
  • 使用Python高效获取网络数据的操作指南

    使用Python高效获取网络数据的操作指南

    网络爬虫是一种自动化程序,用于访问和提取网站上的数据,Python是进行网络爬虫开发的理想语言,拥有丰富的库和工具,使得编写和维护爬虫变得简单高效,本文将详细介绍如何使用Python进行网络爬虫开发,包括基本概念、常用库、数据提取方法、反爬措施应对以及实际案例
    2025-03-03

最新评论