Python 具名元组——我不只是不可变列表

封面.jpg

Intro

很多 Python 入门资料会将元组 (tuple) 介绍为 "不可变列表", 因其具备可迭代和可切片的能力, 同时无法修改元组中的值而得名. 然而这只是元组的其中一个特性而已.

元组的本质

元组是对数据的一个记录, 每个位置记录了某个字段的值, 位置和字段信息赋予了这组数据的意义. 听起来很像数据库中的某条数据记录, 假如数据的元素不保持某个固定的位置, 你还认为这个数据是可用的吗?

具名元组 —— 元组特性的最有力体现

具名元组来自 Python 内置库 collections.nametupled 中, 可以用来构建带字段名的元组和一个相应的类

使用 nametupled 构建的类的实例所消耗的内存与元组是一致的, 因为字段名都被保存在对应的类里面.
—— 译自 Fluent Python

声明方式一

nametuple 构造函数的首个参数为类名, 第二个参数为字段名信息, 可以是以空格隔开的字符串, 也可以是字符串数组.

In [14]: from collections import namedtuple

In [15]: UserInfo = namedtuple('UserInfo', 'username passwor
    ...: d block vip')

In [16]: coding = UserInfo('coding', 'ShowMeTheCode', '0', '
    ...: 1')

In [17]: coding.password
Out[17]: 'ShowMeTheCode'

In [18]: coding[1]
Out[18]: 'ShowMeTheCode'

声明方式二

这种方式利用了很 Pythonic 的解包方式进行声明

In [19]: columns = ['name', 'city', 'email']

In [20]: Contact = namedtuple('Contact', columns)

In [21]: contact = ['coding', 'Dongguan', 'fesonx@foxmail.co
    ...: m']

In [22]: coding_contact = Contact(*contact)

In [23]: coding_contact.city
Out[23]: 'Dongguan'

可以用元组进行解包声明, 这里就充分利用了元组的位置信息:

In [40]:  contact_desciption = ('Contact', ['name', 'city', 'email', 'phone'])

In [41]: Contact = namedtuple(*contact_desciption)

用途

  1. 面向对象
    在日常开发中, 往往离不开关系型数据库对象和缓存, 以往使用 ORM 框架时, 受益于 ORM 面向对象的思想, 可以很方便的用 instance.field 方式访问对象属性, 但是转化到缓存时, 特别是类似 Redis 这类只保存字节的缓存, 就失去了对象这一概念.
    以往我们常常使用字典来"挽回"一点面向对象的思想, 但是如前文引用所示, 不保存字段名的具名元组实例要比字典占用的内存小, 并且在获取对象属性时要比字典方便多了, 面向对象的思想得到体现.
In [35]: coding_dict = {"name": "coding", "city": "Dongguan", "email": "fesonx@fox
    ...: mail.com"}

In [36]: coding_dict.get('name') # 字典
Out[36]: 'coding'

In [37]: coding_contact.name # 具名元组
Out[37]: 'coding'
  1. 转化为(类)字典对象
    日常开发中之所以会使用字典来保存缓存的内容, 很重要的原因是为了方便解析为 json 格式返回, 以往的 ORM 对象 (如 Flask-SQLALchemy) 如不引用外部框架, 一般也不具备转为键值的能力. 而具名字典正有这样的特性, 利用内置的 _asdict() 方法即可:
In [20]: Contact = namedtuple('Contact', columns)

In [21]: contact = ['coding', 'Dongguan', 'fesonx@foxmail.co
    ...: m']

In [22]: coding_contact = Contact(*contact)

In [26]: coding_contact._asdict()
Out[26]:
OrderedDict([('name', 'coding'),
             ('city', 'Dongguan'),
             ('email', 'fesonx@foxmail.com')])

In [27]: import json

In [28]: json.dumps(coding_contact._asdict())
Out[28]: '{"name": "coding", "city": "Dongguan", "email": "fesonx@foxmail.com"}'

字典可以使用 .keys() 方法来得到键名列表, 而具名元组可以使用 ._fields 属性获得一个字段元组, 用来判断前端传入的排序属性是否存在非常方便:

In [48]: Contact._fields
Out[48]: ('name', 'city', 'email', 'phone')

In [49]: 'city' in Contact._fields
Out[49]: True

欢迎关注公众号: 程序员的碎碎念

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,490评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,581评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,830评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,957评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,974评论 6 393
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,754评论 1 307
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,464评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,357评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,847评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,995评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,137评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,819评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,482评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,023评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,149评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,409评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,086评论 2 355

推荐阅读更多精彩内容

  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 11,105评论 1 32
  • 一. Java基础部分.................................................
    wy_sure阅读 3,811评论 0 11
  • 1.JVM 堆内存和非堆内存 堆和非堆内存按照官方的说法:“Java 虚拟机具有一个堆(Heap),堆是运行时数据...
    yanzhu728阅读 915评论 0 0
  • ORA-00001: 违反唯一约束条件 (.) 错误说明:当在唯一索引所对应的列上键入重复值时,会触发此异常。 O...
    我想起个好名字阅读 5,321评论 0 9
  • 昨夜,大雨滂沱,我躺在床上静听雨声,骤雨密集,铿锵有力,却也凌乱急切,想你。从窗外望去,夏雨气势磅礴,遮天蔽日的酣...
    华枝春满5339阅读 543评论 4 7