Python之namedtuple源码分析建议收藏

namedtuple函数源码通过函数模板字符串_class_template.format()会生成我们需要的实例类:eg:people=namedtuple("person&qu

大家好,又见面了,我是全栈君,今天给大家准备了Idea注册码。

Python之namedtuple源码分析建议收藏此处内容已经被作者隐藏,请输入验证码查看内容
验证码:
请关注本站微信公众号,回复“”,获取验证码。在微信里搜索“”或者“”或者微信扫描右侧二维码都可以关注本站微信公众号。

namedtuple()函数根据提供的参数创建一个新类,这个类会有一个类名,一些字段名和一个可选的用于定义类行为的关键字,具体实现如下

namedtuple函数源码

from keyword import iskeyword as _iskeyword import sys as _sys import logging logging.basicConfig(level=logging.INFO, filename="logging.txt", filemode="w+", \ format = '%(asctime)s - %(name)s - %(levelname)s - %(message)s') logger = logging.getLogger(__name__) _class_template = """\ from builtins import property as _property, tuple as _tuple from operator import itemgetter as _itemgetter from collections import OrderedDict class {typename}(tuple): '{typename}({arg_list})' __slots__ = () _fields = {field_names!r} def __new__(_cls, {arg_list}): 'Create new instance of {typename}({arg_list})' return _tuple.__new__(_cls, ({arg_list})) @classmethod def _make(cls, iterable, new=tuple.__new__, len=len): 'Make a new {typename} object from a sequence or iterable' result = new(cls, iterable) if len(result) != {num_fields:d}: raise TypeError('Expected {num_fields:d} arguments, got %d' % len(result)) return result def _replace(_self, **kwds): 'Return a new {typename} object replacing specified fields with new values' result = _self._make(map(kwds.pop, {field_names!r}, _self)) if kwds: raise ValueError('Got unexpected field names: %r' % list(kwds)) return result def __repr__(self): 'Return a nicely formatted representation string' return self.__class__.__name__ + '({repr_fmt})' % self def _asdict(self): 'Return a new OrderedDict which maps field names to their values.' return OrderedDict(zip(self._fields, self)) def __getnewargs__(self): 'Return self as a plain tuple. Used by copy and pickle.' return tuple(self) {field_defs} """ _repr_template = '{name}=%r' _field_template = '''\ {name} = _property(_itemgetter({index:d}), doc='Alias for field number {index:d}') ''' def namedtuple(typename, field_names, *, verbose=False, rename=False, module=None): """Returns a new subclass of tuple with named fields. >>> Point = namedtuple('Point', ['x', 'y']) >>> Point.__doc__ # docstring for the new class 'Point(x, y)' >>> p = Point(11, y=22) # instantiate with positional args or keywords >>> p[0] + p[1] # indexable like a plain tuple 33 >>> x, y = p # unpack like a regular tuple >>> x, y (11, 22) >>> p.x + p.y # fields also accessible by name 33 >>> d = p._asdict() # convert to a dictionary >>> d['x'] 11 >>> Point(**d) # convert from a dictionary Point(x=11, y=22) >>> p._replace(x=100) # _replace() is like str.replace() but targets named fields Point(x=100, y=22) """ # Validate the field names. At the user's option, either generate an error # message or automatically replace the field name with a valid name. if isinstance(field_names, str): field_names = field_names.replace(',', ' ').split() field_names = list(map(str, field_names)) typename = str(typename) logging.info("%s: %s" %(typename, field_names)) if rename: seen = set() for index, name in enumerate(field_names): if (not name.isidentifier() or _iskeyword(name) or name.startswith('_') or name in seen): field_names[index] = '_%d' % index seen.add(name) for name in [typename] + field_names: logging.info(name) if type(name) is not str: raise TypeError('Type names and field names must be strings') #判断是否为标识符,标识符必须以字母或者“_”开头 #标识符用于作为变量,函数名、类名、方法名等 if not name.isidentifier(): raise ValueError('Type names and field names must be valid ' 'identifiers: %r' % name) #判断是否为关键字,关键字为python内部已经使用了的标识符  if _iskeyword(name): raise ValueError('Type names and field names cannot be a ' 'keyword: %r' % name) seen = set() for name in field_names: if name.startswith('_') and not rename: raise ValueError('Field names cannot start with an underscore: ' '%r' % name) if name in seen: raise ValueError('Encountered duplicate field name: %r' % name) seen.add(name) # Fill-in the class template class_definition = _class_template.format( typename = typename, field_names = tuple(field_names), num_fields = len(field_names), arg_list = repr(tuple(field_names)).replace("'", "")[1:-1], repr_fmt = ', '.join(_repr_template.format(name=name) for name in field_names), field_defs = '\n'.join(_field_template.format(index=index, name=name) for index, name in enumerate(field_names)) ) logging.info(class_definition) # Execute the template string in a temporary namespace and support # tracing utilities by setting a value for frame.f_globals['__name__'] namespace = dict(__name__='namedtuple_%s' % typename) exec(class_definition, namespace) result = namespace[typename] result._source = class_definition if verbose: print(result._source) # For pickling to work, the __module__ variable needs to be set to the frame # where the named tuple is created. Bypass this step in environments where # sys._getframe is not defined (Jython for example) or sys._getframe is not # defined for arguments greater than 0 (IronPython), or where the user has # specified a particular module. if module is None: try: module = _sys._getframe(1).f_globals.get('__name__', '__main__') except (AttributeError, ValueError): pass if module is not None: result.__module__ = module return result

  通过函数模板字符串_class_template.format()会生成我们需要的实例类:

  eg: people = namedtuple(“person”,”name,age,sex”) 

class person(tuple) 分析

#coding=utf-8 from builtins import property as _property, tuple as _tuple from operator import itemgetter as _itemgetter from collections import OrderedDict import logging logging.basicConfig(level=logging.INFO, filename="logging.txt", filemode="w+", \ format = '%(asctime)s - %(name)s - %(levelname)s - %(message)s') logger = logging.getLogger(__name__) class person(tuple): 'person(name, age, sex)' __slots__ = () _fields = ('name', 'age', 'sex') def __new__(_cls, name, age, sex): 'Create new instance of person(name, age, sex)' logger.info("__new__") return _tuple.__new__(_cls, (name, age, sex)) @classmethod def _make(cls, iterable, new=tuple.__new__, len=len): 'Make a new person object from a sequence or iterable' result = new(cls, iterable) if len(result) != 3: raise TypeError('Expected 3 arguments, got %d' % len(result)) return result def _replace(_self, **kwds): 'Return a new person object replacing specified fields with new values' #需要深刻理解该代码的精髓  logger.info(type(_self)) for item in _self: logger.info(item) str = ''' how to replace dict_keyvalue li = map({"age":99}.pop, ('name', 'age', 'sex'), ("zhanglin", "11", "man")) ''' logger.info(str) result = _self._make(map(kwds.pop, ('name', 'age', 'sex'), _self)) if kwds: raise ValueError('Got unexpected field names: %r' % list(kwds)) return result def __repr__(self): 'Return a nicely formatted representation string' return self.__class__.__name__ + '(name=%r, age=%r, sex=%r)' % self def _asdict(self): 'Return a new OrderedDict which maps field names to their values.' return OrderedDict(zip(self._fields, self)) #打包为元组列表 def __getnewargs__(self): 'Return self as a plain tuple. Used by copy and pickle.' return tuple(self) name = _property(_itemgetter(0), doc='Alias for field number 0') age = _property(_itemgetter(1), doc='Alias for field number 1') sex = _property(_itemgetter(2), doc='Alias for field number 2') if __name__ == "__main__": p1 = person("zhanglin", "30", "man") logger.info("{0}:{1}".format("p1", p1)) #_replace验证  p2 = p1._replace(name ="zhangsan", age=99) logger.info(p2) logger.info("{0}:{1}".format("p2", p2)) 

测试结果:

2018-03-21 15:10:46,197 - __main__ - INFO - __new__ 2018-03-21 15:10:46,197 - __main__ - INFO - p1:person(name='zhanglin', age='30', sex='man') 2018-03-21 15:10:46,197 - __main__ - INFO - <class '__main__.person'> 2018-03-21 15:10:46,197 - __main__ - INFO - zhanglin 2018-03-21 15:10:46,197 - __main__ - INFO - 30 2018-03-21 15:10:46,197 - __main__ - INFO - man 2018-03-21 15:10:46,197 - __main__ - INFO - how to replace dict_keyvalue li = map({"age":99}.pop, ('name', 'age', 'sex'), ("zhanglin", "11", "man")) 2018-03-21 15:10:46,197 - __main__ - INFO - person(name='zhangsan', age=99, sex='man') 2018-03-21 15:10:46,197 - __main__ - INFO - p2:person(name='zhangsan', age=99, sex='man')

根据类的字符串模板创建类

#coding=utf-8 import logging logging.basicConfig(level=logging.INFO, filename="logging.txt", filemode="w+",\ format = '%(asctime)s - %(name)s - %(levelname)s - %(message)s') logger = logging.getLogger(__name__) _class_template = \ ''' class {typename}(tuple): __slots__ = () _fields = {field_names!r} def __new__(cls, *args, **dwargs): return super().__new__(cls, *args, **dwargs) ''' def defineclass(typename, field_names): logging.info(field_names) class_definition = _class_template.format(typename=typename,field_names=field_names,\ #方法1 arg_list = ','.join(name for name in field_names),\ self_format = "".join("\t\tself.{name}={name}\n".format(name=name) for name in field_names)) #方法2 #arg_list = ', '.join('{name}'.format(name=name) for name in field_names)) #方法3 #arg_list = repr(tuple(field_names)).replace("'", "")[1:-1])  logging.info(class_definition) namespace = dict(__name__='defineclass_%s' % typename) logging.info("namespce:{}".format(namespace)) exec(class_definition, namespace) result = namespace[typename] logging.info("typename:{0}--result:{1}".format(typename, namespace[typename])) result._source = class_definition return result if __name__ == "__main__": person = defineclass("person", ("name", "age", "sex")) print (type(person)) p = person(("zhanglin", "31", "man")) print (p) print (p[0])
2018-03-22 00:05:50,705 - root - INFO - ('name', 'age', 'sex') 2018-03-22 00:05:50,705 - root - INFO - class person(tuple): __slots__ = () _fields = ('name', 'age', 'sex') def __new__(cls, *args, **dwargs): return super().__new__(cls, *args, **dwargs) 2018-03-22 00:05:50,705 - root - INFO - namespce:{'__name__': 'defineclass_person'} 2018-03-22 00:05:50,705 - root - INFO - typename:person--result:<class 'defineclass_person.person'>

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/120187.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • 一些安全扫描工具_web弱口令扫描工具

    一些安全扫描工具_web弱口令扫描工具术语表术语定义敏感数据敏感数据的具体范围取决于产品具体的应用场景,产品应根据风险进行分析和判断。典型的敏感数据包括口令、银行帐号、大批量个人数据、用户通信内容和密钥等。一类如果丢失或者泄漏,会对数据的所有者造成负面影响的数据。本基线定义的“敏感数据”包括但不限于:口令、通行码、密钥、证书、License、隐私数据(如短消息的内容)、授权凭…

  • 无人机指挥系统中标价_云睿智能无人机

    无人机指挥系统中标价_云睿智能无人机为什么大规模数字孪生很重要?Geopipe数据如何独特地使开发人员能够构建创新的空间产品?犹他大学的一个跨学科团队为无人机系统(UnmannedAerialSystems,UAS)…

  • SMO算法笔记及个人理解

    SMO算法笔记及个人理解SMO算法介绍SMO算法是一种启发式算法,其基本思路是:如果所有变量的解都满足此优化问题的KKT条件,那么这个最优化问题的解就得到了。(KKT条件是该最优化问题的充分必要条件)。否则,选择两个变量,固定其他变量针对这两个变量构建一个二次规划问题。特点:将原始的二次规划问题分解为只含有两个变量的二次规划子问题,对子问题不断求解,使得所有的变量满足KKT条件包含两部分:1、求解两个变量二次规划的解析方法2、选择变量的启发式方法(1)第1个变量的选择:确定在当前的分类器中,违反K.

  • 如何安装打印机_vs2010旗舰版安装教程

    如何安装打印机_vs2010旗舰版安装教程按照默认安装vs2005sp1,往往不会成功。需要做如下设置.1.运行secpol.msc2.在左边栏,右键“软件限制策略”,新建3.双击右边栏中的强制,选择“除本地管理员以外的所有用户”如上设置后,再安装vs2005sp1即可成功安装。 …

  • google earth engine(GEE)监督分类总结与代码分享

    google earth engine(GEE)监督分类总结与代码分享提供分类代码以及思路整理

  • MAC-npm更新版本「建议收藏」

    参考连接:参考连接运行下面的命令,查看npm可更新的版本:npm-goutdated输入一下命令,更新对应的版本:sudonpm-ginstallnpm@4.4.4在这里安装可能会报错:ENOTEMPTY:directorynotempty,rename’/usr/local/lib/node_modules/npm’->’/usr/local/lib/no

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号