映射名称到序列元素

问题

你有一段通过下标访问列表或者元组中元素的代码,但是这样有时候会使得你的代码难以阅读,于是你想通过名称来访问元素。

解法

collections.namedtuple() 函数通过使用一个普通的元组对象来帮你解决这个问题。这个函数实际上是一个返回 Python 中标准元组类型子类的一个工厂方法。你需要传递一个类型名和你需要的字段给它,然后它就会返回一个类,你可以初始化这个类,为你定义的字段传递值等。代码示例:

>>> from collections import namedtuple
>>> Subscriber = namedtuple('Subscriber', ['addr', 'joined'])
>>> sub = Subscriber('jonesy@example.com', '2012-10-19')
>>> sub
Subscriber(addr='jonesy@example.com', joined='2012-10-19')
>>> sub.addr
'jonesy@example.com'
>>> sub.joined
'2012-10-19'
>>>

尽管 namedtuple 的实例看起来像一个普通的类实例,但是它跟元组类型是可交换的,支持所有的普通元组操作,比如索引和拆分。比如:

>>> len(sub)
2
>>> addr, joined = sub
>>> addr
'jonesy@example.com'
>>> joined
'2012-10-19'
>>>

命名元组的一个主要用途是将你的代码从下标操作中解脱出来。因此,如果你从数据库调用中返回了一个很大的元组列表,通过下标去操作其中的元素,当你在表中添加了新的列的时候你的代码可能就会出错了。但是如果你使用了命名元组,那么就不会有这样的顾虑。(避免魔数

为了说明清楚,下面是使用普通元组的代码:

def compute_cost(records):
total = 0.0
for rec in records:total += rec[1] * rec[2]
return total

下标操作通常会让代码表意不清晰,并且非常依赖记录的结构。下面是使用命名元组的版本:

from collections import namedtupleStock = namedtuple('Stock', ['name', 'shares', 'price'])def compute_cost(records):total = 0.0for rec in records:s = Stock(*rec)total += s.shares * s.pricereturn total

讨论

命名元组另一个用途就是作为字典的替代,因为字典存储需要更多的内存空间(节省空间)。如果你需要构建一个非常大的包含字典的数据结构,那么使用命名元组会更加高效。但是需要注意的是,不像字典那样,一个命名元组是不可更改的。比如:

>>> s = Stock('ACME', 100, 123.45)
>>> s
Stock(name='ACME', shares=100, price=123.45)
>>> s.shares = 75
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: can't set attribute
>>>

如果你真的需要改变然后的属性,那么可以使用命名元组实例的_replace() 方法,它会创建一个全新的命名元组并将对应的字段用新的值取代。比如:

>>> s = s._replace(shares=75)
>>> s
Stock(name='ACME', shares=75, price=123.45)
>>>

_replace() 方法还有一个很有用的特性就是当你的命名元组拥有可选或者缺失字段时候,它是一个非常方便的填充数据的方法。你可以先创建一个包含缺省值的原型元组,然后使用_replace() 方法创建新的值被更新过的实例。比如:

from collections import namedtuple
Stock = namedtuple('Stock', ['name', 'shares', 'price', 'date', 'time'])# Create a prototype instance
stock_prototype = Stock('', 0, 0.0, None, None)# Function to convert a dictionary to a Stock
def dict_to_stock(s):
return stock_prototype._replace(**s)

下面是它的使用方法:

>>> a = {'name': 'ACME', 'shares': 100, 'price': 123.45}
>>> dict_to_stock(a)
Stock(name='ACME', shares=100, price=123.45, date=None, time=None)
>>> b = {'name': 'ACME', 'shares': 100, 'price': 123.45, 'date': '12/17/2012'}
>>> dict_to_stock(b)
Stock(name='ACME', shares=100, price=123.45, date='12/17/2012', time=None)
>>>

最后要说的是,如果你的目标是定义一个需要更新很多实例属性的高效数据结构,那么命名元组并不是你的最佳选择。这时候你应该考虑定义一个包含 slots 方法的类 (参考 8.4 小节)。

《Python Cookbook 3rd》笔记(1.18):映射名称到序列元素相关推荐

  1. 《Python Cookbook 3rd》笔记汇总

    文章目录 一.数据结构 二.字符串和文本 三.数字.日期和时间 四.迭代器与生成器 五.文件与IO 一.数据结构 标题 关键词 1.1:拆分序列后赋值给多个变量 可迭代对象.拆分赋值 1.2:拆分任意 ...

  2. 《Python cookbook》笔记一

    <Python cookbook> 第一章 数据结构和算法 - *号解压多个变量 - 如果一个可迭代对象的元素个数超过变量个数时,会抛出一个 ValueError .那么 怎样才能从这个可 ...

  3. 《Python Cookbook 3rd》笔记(1.4):查找最大或最小的N个元素

    <Python Cookbook 3rd>1.4:查找最大或最小的N个元素 问题 怎样从一个集合中获得最大或者最小的N个元素列表? 解法 heapq 模块有两个函数:nlargest()和 ...

  4. Python Cookbook 3rd Edition Documentation

    Python Cookbook 3rd Edition Documentation 文章目录 第一章:数据结构和算法 1.1 解压序列赋值给多个变量 问题 解决方案 讨论 1.2 解压可迭代对象赋值给 ...

  5. Machine Learning with Python Cookbook 学习笔记 第6章

    Chapter 6. Handling Text 本笔记是针对人工智能典型算法的课程中Machine Learning with Python Cookbook的学习笔记 学习的实战代码都放在代码压缩 ...

  6. Machine Learning with Python Cookbook 学习笔记 第9章

    Chapter 9. Dimensionality Reduction Using Feature Extraction 前言 本笔记是针对人工智能典型算法的课程中Machine Learning w ...

  7. 《Python cookbook》笔记二

    <Python cookbook>笔记二 第二章 字符串和文本 -使用多个界定符分割字符串- 你需要将一个字符串分割为多个字段,但是分隔符 (还有周围的空格) 并不是固定 的. # str ...

  8. Machine Learning with Python Cookbook 学习笔记 第8章

    Chapter 8. Handling Images 前言 本笔记是针对人工智能典型算法的课程中Machine Learning with Python Cookbook的学习笔记 学习的实战代码都放 ...

  9. 《Python Cookbook 3rd》笔记(1.1):拆分序列后赋值给多个变量

    拆分序列后赋值给多个变量 问题 现有一个包含N个元素的元组或序列,如何将其值拆分后同时赋值给N个变量? 解法 任何序列 (或可迭代对象) 可通过一个简单赋值语句拆分并赋值给多个变量.唯一前提是变量数量 ...

最新文章

  1. linux严谨的telnet搭建并用防火墙开通与禁行
  2. php和python学哪个-PHP Vs Python 学习哪个比较好?
  3. 计算是计算机科学独有的方法,大学计算机基础教学中的计算思维培养.doc
  4. FFmpeg AVCodecContext结构体debug变量剖析
  5. JavaScript中ajax如何不刷新,JavaScript基于Ajax实现不刷新在网页上动态显示文件内容...
  6. 1个人,耗时2年半,这款大型仙侠3D硬核ARPG是怎么做出来的?
  7. .net函数查询_SQL查询语句总是先执行SELECT?你们都错了!
  8. Mr.J--谈谈CSS和Html(font)
  9. Linux+varnish安装配置
  10. ASP.net 的URL路由选择(System.Web.Routing.dll)
  11. python 类命名空间,关于python:命名空间和类
  12. 【红顶商人胡雪岩】-- 读完一点小感
  13. 游侠原创:VMware ESXi 5安装图文教程
  14. MediaCreationTool工具重装win10系统(小白专用)
  15. 两数之和c++实现 java实现 two sum
  16. 常见嵌入式OS资料汇总
  17. 《人生哲理》二.人生苦短,别懂得太晚了...
  18. 无货源开店已确认违法
  19. 五险一金 | 养老保险及其退休金计算
  20. 【二胡音乐】陈军《胡弓传奇》

热门文章

  1. android unzip file,Unzip File in Android Assets
  2. websocket多人聊天php,php-notes/基于websocket实现多人聊天室.md at master · dd-code-site/php-notes · GitHub...
  3. 【转】交织容积重建技术:基本原理与临床价值
  4. linux make怎么运行,Linux Make 命令教程
  5. 集卡php源码,独角数卡自动发卡网PHP源码+教程:虚拟产品自助售卖
  6. Qt: QTableView如何获取(行)选中、行切换信息
  7. Python 数据分析三剑客之 Matplotlib(一):初识 Matplotlib 与其 matplotibrc 配置文件
  8. CCNA-第一篇-基础入门概念
  9. 10.深度学习练习:Convolutional Neural Networks: Step by Step(强烈推荐)
  10. SM3密码杂凑算法源码解析