突破常规:揭秘我在学习 Python 容器时的新收获

前言

Python代码也写了好长时间了,回过头来再看基础知识,还是颇有收获,这里记录一下自己再看容器类型的收获

元组

我们都知道定义元组像下面这样使用()

ini 复制代码
t = (1, 2, 3)

其实,()不是定义元组的关键标志,我们删除两侧的括号,像这样

bash 复制代码
t = 1, 2, 3
print(type(t)) # <class 'tuple'>

可以看到,这样也是一个元组,逗号才是解释器判定为元组的关键

所以,如果一个元组只有一个元素时,是需要加逗号的,像这样

ini 复制代码
t = (1,)

如果不加逗号,类型就不是元组了。

具名元组

使用元组存放数据,给我们带来的不便就是,不容易知道值代表的是啥,所以具名元组就出现了。

具名元组,允许为元组的每个成员命名,方便通过名称来访问,像这样

ini 复制代码
import collections
​
Point = collections.namedtuple('Point', ['x', 'y'])
p = Point(11, y=22)
print(p.x, p.y) # 输出结果:11 22

当然这是通用的方法,如果在高版本(3.6以后),还可以使用typing模块来定义具名数组类型,像这样

python 复制代码
from typing import NamedTuple
​
​
class Point(NamedTuple):
    x: int
    y: int
p = Point(11, 22)
print(p.x, p.y) # 输出结果:11 22

这种写法,看着可读性更强。

字典

使用键值访问字典内容时,为了防止出现,键不存在导致报错KeyError,我们通常会增加判断,像这样

bash 复制代码
dic = {"name": "panda", "age": 18}
if 'sex' in dic:
    print(dic['sex'])
else:
    print('sex not in dic')

当然还有另外一种写法,像这样

python 复制代码
dic = {"name": "panda", "age": 18}
try:
    print(dic['sex'])
except KeyError:
    print('sex not in dic')

看着这种写法更加简洁。

如果访问键不存在时,给一个默认值,可以使用get方法,像这样

bash 复制代码
dic = {"name": "panda", "age": 18}
print(dic.get("sex", "男")) # 男

现在,有这样一个需求,给定一个列表,将列表中的值作为字典的键,值默认为空列表,我们是这样实现的

ini 复制代码
dic = {}
words = ['apple', 'banana', 'orange', 'pear', 'peach']
for word in words:
    dic[word] = []

但我们如果使用collections.defaultdict就会简洁很多,像这样

ini 复制代码
import collections
dic = collections.defaultdict(list)

这行代码创建了一个defaultdict对象,其中list是指定的默认值类型。

删除键,如果键不存在,我们需要增加判断,像这样

python 复制代码
dic = {"name": "panda", "age": 18}
try:
    del dic['sex']
except KeyError:
    print('sex not in dic')

当然也可以使用pop方法,像这样

ini 复制代码
dic = {"name": "panda", "age": 18}
dic.pop("sex", None)

调用pop方法时传入默认值None,这样键不存在也不会出现异常。当然pop最大的作用是用来取删除键对应的值。

有序 or 无序

之前我都觉得:字典是无序的,其实在Python3.6以后字典变得有序了。当然collections.OrderedDict也可以保证字典的有序性。

注意:只有可哈希对象才可以作为字典的键

集合

我们都知道集合是一种无序的可变容器类型,特点就是不能重复。

我们可以使用add方法添加集合元素,像这样

ini 复制代码
set_ = {1, 2, 3}
set_.add(4)
print(set_) # {1, 2, 3, 4}

如果我们想要一个不可变的集合,可以使用内置类型frozenset,像这样

scss 复制代码
set_ = frozenset([1, 2, 3])
set_.add(4) # AttributeError: 'frozenset' object has no attribute 'add'

集合,求交集、并集、差集,像这样

scss 复制代码
set_1 = set([1, 2, 3, 5])
set_2 = set([1, 2, 3, 4])
​
print(set_1 & set_2) # {1, 2, 3}
print(set_1 | set_2) # {1, 2, 3, 4, 5}
print(set_1 - set_2) # {5} 前一个集合有后一个集合没有

当然也可以使用方法实现,像这样

scss 复制代码
set_1 = set([1, 2, 3, 5])
set_2 = set([1, 2, 3, 4])
​
​
print(set_1.intersection(set_2)) # 交集
print(set_1.union(set_2)) # 并集
print(set_1.difference(set_2)) # 差集

集合只能存放可哈希对象,像这样

ini 复制代码
set_1 = {[1, 2, 3, 5]}
print(set_1) # TypeError: unhashable type: 'list'

提示我们列表是不可哈希的,判断是不是可哈希可以使用hash()。可变的内置类都是不可哈希的,比如字典、列表,当然可哈希的不一定永远可哈希,比如不可变容器类型元组,原本是可哈希的,如果元素包含列表,就变为了不可哈希,像这样

ini 复制代码
tup = (1, 2, 3, 5)
print(hash(tup)) # 7098540143285066217
​
tup_new = ([1, 2], 3, 5)
print(hash(tup_new)) # TypeError: unhashable type: 'list'

注意:用户自己定义的对象,默认都是可哈希的

最后

Python好入门,但想要更上一层,还需要基础更扎实一些。

相关推荐
bobz9652 分钟前
VRRP 简记
后端
冯仙笙8 分钟前
统一支付入口集成六种支付方式
后端
无双_Joney20 分钟前
[更新迭代 - 1] Nestjs 在24年底更新了啥?(功能篇)
前端·后端·nestjs
数据智能老司机25 分钟前
精通 Python 设计模式——并发与异步模式
python·设计模式·编程语言
数据智能老司机26 分钟前
精通 Python 设计模式——测试模式
python·设计模式·架构
数据智能老司机26 分钟前
精通 Python 设计模式——性能模式
python·设计模式·架构
泉城老铁28 分钟前
idea 优化卡顿
前端·后端·敏捷开发
福大大架构师每日一题34 分钟前
RustDesk 1.4.2 版本发布:新增增量文件传输与光标显示功能
后端
LH_R35 分钟前
OneTerm开源堡垒机实战(四):访问授权与安全管控
运维·后端·安全
poemyang35 分钟前
技术圈的“绯闻女孩”:Gossip是如何把八卦秘密传遍全网的?
后端·面试·架构