前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Python 具名元组——我不只是可不变列表

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

作者头像
benny
发布2019-11-19 12:50:35
8730
发布2019-11-19 12:50:35
举报

Intro

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

元组的本质

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

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

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

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

声明方式一

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

代码语言:javascript
复制
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 的解包方式进行声明

代码语言:javascript
复制
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'

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

代码语言:javascript
复制
In [40]:  contact_desciption = ('Contact', ['name', 'city', 'email', 'phone'])

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

1. 面向对象

在日常开发中, 往往离不开关系型数据库对象和缓存, 以往使用 ORM 框架时, 受益于 ORM 面向对象的思想, 可以很方便的用 instance.field 方式访问对象属性, 但是转化到缓存时, 特别是类似 Redis 这类只保存字节的缓存, 就失去了对象这一概念.

以往我们常常使用字典来"挽回"一点面向对象的思想, 但是如前文引用所示, 不保存字段名的具名元组实例要比字典占用的内存小, 并且在获取对象属性时要比字典方便多了, 面向对象的思想得到体现.

代码语言:javascript
复制
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'

2. 转化为(类)字典对象

日常开发中之所以会使用字典来保存缓存的内容, 很重要的原因是为了方便解析为 json 格式返回.

以往的 Python ORM 对象 (如 Flask-SQLALchemy) 如不引用外部框架, 一般也不具备转为键值的能力. 而具名元组正有这样的特性, 利用内置的 _asdict() 方法即可:

代码语言:javascript
复制
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 属性获得一个字段元组, 用来判断前端传入的排序属性是否存在非常方便:

代码语言:javascript
复制
In [48]: Contact._fields
Out[48]: ('name', 'city', 'email', 'phone')

In [49]: 'city' in Contact._fields
Out[49]: True
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-11-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 程序员的碎碎念 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Intro
  • 元组的本质
  • 具名元组 —— 元组特性的最有力体现
    • 声明方式一
      • 声明方式二
        • 用途
        相关产品与服务
        数据库
        云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档