Python-collections 集合 - 容器数据类型

发布于 2024-08-01 23:07:57 字数 4486 浏览 12 评论 0

namedtuple

自 Python 2.6 开始,namedtuple 就加入到 python 里,用以 只有少数属性 但是没有方法的对象

import collections
nt = collections.namedtuple('nt', ['attr1', 'attr2'])
# 相当于定义了一个类,类名是 nt 他有属性 attr1 attr2
# 可以通过 i = nt(val1, val2) 对类进行实例化, 然后 i.attr1 i.attr2 访问属性

元组(tuple) 是 Python 中常见的数据类型之一,和列表(list) 相似,不同的地方在于列表是可变数组,而 tuple 是一个不可变的数组,你不能改变元组中的值

>>> bar = ("bob", 10)
>>> bar[1] = 11
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment
# 错误提示很清晰的告诉你 tuple 不支持元素重新赋值

元组除了可以看做是不可变的列表之外,还可以当做没有字段名的记录(record)。比如从一个数据库的用户表中查询出一条记录包含有:姓名、性别、身高、体重这四个字段的值,用元组来表示这条记录是:

name, gender, height, weight = ("jack", "female", 170, 120)

使用元组表示一条记录从性能上来说是要超过列表,因为列表是可变对象,列表内部维护的东西更多,而元组则更轻量级。但是,元组当做记录有一个缺点,你不知道元组中的每一项具体代表什么意思,只有你自己知道,如果你是 API 的提供方,调用者使用你的 API 时,只有通过文档说明才知道你的元组中的元素各代表什么意思,如果那些需求变更,而文档没有及时更新,调用者很容易就出问题了。每次取值时,我们只能通过下标索引第 0 号,第 1 号,第 2 号

这时就可以用一种更加高级的元组叫 namedtuple ,《流畅的 Python》上把它翻译为 具名元组 ,取值时不再需要通过下标索引的方式来获取了

from collections import namedtuple
# 定义 namedtuple 类
User = namedtuple("User", 'name gender height weight')
# 或者
# User = namedtuple("User", ['name', 'gender', 'height', 'weight'])

# 初始化 namedtuple 实例对象
user = User(name="jack", gender="female", height=170, weight=120)
# 访问都应的属性
user.name    #'jack'
user.gender   #'female'

定义 namedtuple 时,第一个参数就是 元组的名字 ,这里很像我们自定义类中的类名,第二个参数是用空格隔开的字符串(也可以是字符串组成的列表),代表元组中的 4 个字段,相当于类中的 4 个属性。初始化方式和类的实例对象是一样的,如果用普通类来定义可表示为:

class User:

    def __init__(self, name, gender, height, weight):
        self.name = name
        self.gender = gender
        self.height = height
        self.weight = weight

user = User(name="jack", gender="female", height=170, weight=120)

user.name  #'jack'

对比起来,其实 namedtuple 就是一个轻量级的类,代码更简洁,当我们的类非常简单,只有属性又不需要定义其他方法时,完全可以用 namedtuple 来代替类,使用 namedtuple 效率比使用普通类更高效,同样因为内部不需要维护太多的东西

namedtuple 其实是继承 tuple 的一个子类,它保留了 tuple 的特性,比如通过索引获取元素,切片功能,同样地,字段不能重新赋值

>>> user[1:3]
('female', 170)

>>> user[0]
'jack'

>>> user.name = 'bob'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: can't set attribute

OrderedDict

有序的字典表,会根据元素插入的先后顺序保持

d = collections.OrderedDict()
d['a'] = 'A'
d['b'] = 'B'
d['c'] = 'C'
d['d'] = 'D'
d['e'] = 'E'

for k, v in d.items():
  print(k, v)

相关方法

  • popitem(last=True) : 移除首位对象, 如果 last=ture 则是第一位
  • move_to_end(key, last=True) : 将对应的 key 移到有序字典的最后面

OrderedDict 判断是否相等

除了判断内容是否相等外,还要判断顺序是否相等

# 有序字典判断是否相等
d1 = collections.OrderedDict()
d1['a'] = 'A'
d1['b'] = 'B'

d2 = collections.OrderedDict()
d2['b'] = 'B'
d2['a'] = 'A'

print(d1 == d2)  # False

# 普通字典判断是否相等
d1 = {}
d1['a'] = 'A'
d1['b'] = 'B'

d2 = {}
d2['b'] = 'B'
d2['a'] = 'A'
print(d1 == d2)  # True

Counter(todo)

使用方法是 collections.Counter([iterable-or-mapping])

>>> c = Counter()                           # a new empty counter
>>> c = Counter('gallahad')                 # a new counter from an iterable
# Counter({'g': 1, 'a': 3, 'l': 2, 'h': 1, 'd': 1})
>>> c = Counter({'red': 4, 'blue': 2})      # a new counter from a mapping
>>> c = Counter(cats=4, dogs=8)             # a new counter from keyword args

ChainMap

将多个 dict 或其他映射组合在一起以创建单个可更新视图.通过 [] 查找基础映射,直到找到 key 为止.如果其中一个基础映射得到更新,这些更改将反映在 ChainMap 中.支持所有常用的字典方法.

from collections import ChainMap
toys = {'One': 10, 'Two': 20}
computers = {'iMac': 1000, 'ThinkPad': 800}
clothing = {'Jeans': 40, 'T-shirt': 10}

# 获取 删除
cm = ChainMap(toys, computers, clothing)
cm['Jeans']   # 40
cm.get('Jeans')   # 40
# 只能 pop map[0] 中存在的元素
cm.pop('One')   # 40
cm.get('One')   # KeyError

toys['zhongjiajie'] = 100     # 更新 toys 同时会更新 chainmap
cm.get('zhongjiajie')  # 100

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

羞稚

暂无简介

0 文章
0 评论
22 人气
更多

推荐作者

linfzu01

文章 0 评论 0

可遇━不可求

文章 0 评论 0

枕梦

文章 0 评论 0

qq_3LFa8Q

文章 0 评论 0

JP

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文