Python实用技法第17篇:将名称映射到序列的元素中

news/2024/12/23 8:23:06
上一篇文章: Python实用技法第16篇:从字典中提取子集
下一篇文章: Python实用技法第18篇:同时对数据做转换和换算

1、需求?

我们的代码是通过位置(即索引或下标)来访问列表会元组的,但有时候这会让代码变得有些难以阅读。我们希望可以通过名称来访问元素,以此减少结构中对位置的依赖性。

2、解决方案?

相比普通的元组,collections.namedtuple()(命名元组)只增加了极少的开销就提供了这些便利。实际上collections.namedtuple()是一个工厂方法,它返回的是Python中标准元组类型的子类。我们提供给它一个类型名称以及相应的字段,它就返回一个可实例化的类、为你已经定义好的字段传入值等。

from collections import namedtuple
Subscriber=namedtuple('Subsciber',['addr','joined'])
sub=Subscriber("1782980833@qq.com","2018-10-23")

print(sub)
print(sub.addr)
print(sub.joined)

print(len(sub))
addr,joined=sub
print(addr)
print(joined)

#下面错误,以为你namedtuple是不可变的
#sub.joined="2019"

结果:

Subsciber(addr='1782980833@qq.com', joined='2018-10-23')
1782980833@qq.com
2018-10-23
2
1782980833@qq.com
2018-10-23

尽管namedtuple的实例看起来就像一个普通的类实例,但它的实例与普通的元组是可互换的,而且支持所有普通元组所支持的操作。

命名元组的主要作用在于将代码同它所控制的元素位置间解耦。所以,如果从数据库调用中得到了一个大型的元组列表,而且通过元素的位置来访问元素,那么假如在表单中新增了一列数据,那么代码就会崩溃,但如果首先将返回的元组转换为命名元组,就不会出现问题。

为了说明这个问题,下面有一些使用普通元组的代码:

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

通过位置来引用元素常常使得代码的表达力不够强,而且也很依赖于记录的具体结构。

下面是使用命名元组的版本:

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

3、分析?

namedtuple的一种可能用法是作为字典的替代,后者需要更多的空间来存储。因此,如果要构建设计字典的大型数据,使用namedtuple会更加高效,但是请注意,与字典不同的是,namedtuple是不可变的。

如果需要修改任何属性,可以通过使用namedtuple实例_replace()方法来实现。该方法会创建一个全新的命名元组,并对相应的值做替换。

from collections import namedtuple
Subscriber=namedtuple('Subsciber',['addr','joined'])
sub=Subscriber("1782980833@qq.com","2018-10-23")

print(sub)

sub=sub._replace(joined="2018-10-24")
print(sub)

结果:

Subsciber(addr='1782980833@qq.com', joined='2018-10-23')
Subsciber(addr='1782980833@qq.com', joined='2018-10-24')

_replace()方法有一个微妙的用途,那就是它可以作为一种简单的方法填充具有可选或缺失字段的命名元组。要做到这点,首先创建一个包含默认值得原型数组,然后使用_replace()方法创建一个新的实例,把相应的值替换掉。

from collections import namedtuple
Subscriber=namedtuple('Subsciber',['addr','joined','age'])
sub=Subscriber("",None,0)

def dict_to_stock(s):
    return sub._replace(**s)

a={"addr":"111111@qq.com","joined":"1111-11-11","age":11}
a=dict_to_stock(a)
print(a)

b={"addr":"111111@qq.com","joined":"1111-11-11"}
b=dict_to_stock(b)
print(b)

结果:

Subsciber(addr='111111@qq.com', joined='1111-11-11', age=11)
Subsciber(addr='111111@qq.com', joined='1111-11-11', age=0)

最后,也是相当重要的是,应该要注意如果我们的目标是定义一个高效的数据结构,而且将来会修改各种实例属性,那么使用namedtuple并不是最佳选择,相反,可以考虑顶一个使用了__slots__属性的类。

上一篇文章: Python实用技法第16篇:从字典中提取子集
下一篇文章: Python实用技法第18篇:同时对数据做转换和换算

http://www.niftyadmin.cn/n/4051109.html

相关文章

阿里「Java架构师」 所需要的知识 、评级P6!

选择的范围太广,可以读的书太多,往往容易无所适从。我想就我自己读过的技术书籍中挑选出来一些,按照学习的先后顺序,推荐给大家,特别是那些想不断提高自己技术水平的Java程序员们。一、Java编程入门类 对于没有Java编程…

Android - Ashmem驱动

以下资料摘录整理自老罗的Android之旅博客,是对老罗的博客关于Android底层原理的一个抽象的知识概括总结(如有错误欢迎指出)(侵删):http://blog.csdn.net/luoshengyang/article/details/8923485http://blog…

requireJs和r.js压缩工具

上面release是执行命令 node r.js -o build.js 生成的&#xff0c;需要切换到目录require/tools下面&#xff0c;也就是 有r.js和build.js的目录&#xff0c;才能执行命令 代码目录如上&#xff1a; main.html代码如下&#xff1a; <!DOCTYPE html> <html><head…

遥感卫星快视设备的设计与实现

遥感卫星快视设备的设计与实现 作者&#xff1a;孙磊, 安建平, 卜祥元 遥感卫星在进行地面信源测试时&#xff0c;需要对测试信源进行高速持续大容量记录&#xff0c;以达到测试卫星信源的目的。在一些诸如雷达信号处理、图像通信、高速A/D数据采集等通信和测量领域&#xff0c…

u盘无法格式化怎么办?数据丢失这样恢复

u盘无法格式化怎么办&#xff1f;u盘是大家常用到的一款存储工具&#xff0c;但经常使用也会造成u盘损坏&#xff0c;常见的问题就是u盘无法格式化&#xff0c;这种情况下我们该如何解决呢&#xff1f;数据是否还能恢复呢&#xff1f;下面就一起来了解下u盘修复的方法。 u盘无法…

美化select的jquery插件

自己写的一个美化select插件&#xff0c;浏览器自带的实在太丑&#xff0c;还不能用css自定义。 插件主要原理是隐藏原生的select控件&#xff0c;支持select上设置change事件。 脚本 1 /*2 * iSelect 3 * 自定义select控件4 */5 (function ($) {6 $.fn.iSelect function …

SUSE linux 使用LVM安装系统和管理

引出 在我们安装好linux系统后会发现在需要修改磁盘分区的时候会比较困难,系统安装的/目录的文件系统要更改基本不太可能&#xff0c;其他目录如/home目录也比较困难。但是系统安装时要是采用的LVM管理的方式安装的话就会截然不通。 一、首先普及下LVM的基础知识 LVM&#xff0…

第十二节,运算符

1算数运算 运算符 描述 示例 加&#xff0c;两个对象相加 ab输出结果30 - 减&#xff0c;得到负数&#xff0c;或者一个数减去另一个数 a-b输出结果-10 * 乘&#xff0c;两个数相乘或是返回一个被重复若干次的字符串 a*b输出结果200 / 除&#xf…