PD Python 精粹 2-1运算符、表达式和数据操作

Python 数据操作

本书由电子工业出版社出版,这里仅是在阅读本书中的个人学习笔记,如果侵权,请联系本人删除。纸质书购买请转到这里,本书作者提供的主页请点击这里,作者非常厉害,也是《Python Cookbook, 3rd》的作者。

迭代操作

迭代是一个重要的 Python 特性,所有 Python 容器(列表、元组、字典等)、文件以及生成器函数。下表中的操作可以应用于任何可迭代对象。

操作描述
for vars in s:迭代
v1, v2, ... = s变量析构
x in s, x not in s成员检查
[a, *s, b], (a, *s, b), {a, *s, b}在列表、元组或集合字面量中展开

可迭代对象最基本的操作是 for 循环。这是迭代的方式逐一检查这些值。所有其他操作都以此为基础。

x in s 运算符测试对象 x 是否作为以下运算符生成的项之一出现可迭代对象 s 并返回 TrueFalsex not in s 运算符与 not (x in s) 。对于字符串,innot in 运算符接受子字符串。例如,"hello" in "hello world" 中产生 True。请注意, in 运算符不支持通配符或任何类型的模式匹配。

任何支持迭代的对象都可以将其值解包到一系列地址。

items = [3, 4, 5]
x, y, z = items

letters = "abc"
x, y, z = letters

左侧的地址不必是简单的变量名。任何可以出现在等号的左侧的有效地址是可以接受的。

items = [3, 4, 5]
d = {}
d["x"], d["y"], d["z"] = items

将值解包到位置时,左侧位置的数量必须恰好匹配右侧可迭代项中的项目数。对于嵌套数据结构,匹配位置和数据遵循相同的结构模式。

datetime = ((5, 9, 2008), (10, "30", "am"))
(month, day, year), (hour, minute, am_pm) = datetime

有时候,_ 变量在拆包时可用来表示一个被丢弃的值:

(_, day, _), (hour, _, _) = datetime

如果不知道要解构的项数量,可以使用扩展形式通过包含带星号的变量来解包

items = [1, 2, 3, 4, 5]
a, b, *extra = items
*extra, a, b = items
a, *extra, b = items

*extra 接收所有额外项目,它始终是一个列表。当解构一个可迭代对象时,最多只能使用一个带星号的变量。然而,当解构更复杂的包含不同可迭代对象的数据结构时,则可以使用多个星号变量:

(month, *_), (hour, *_) = datetime

在列出列表、元组和集合字面量时,任何可迭代对象都可以被展开。这也是使用星号(*)完成。

>>> items = [1, 2, 3]
>>> a = [10, *items, 11]
>>> b = (*items, 10, *items)
>>> c = {10, 11, *items}
>>> a
[10, 1, 2, 3, 11]
>>> b
(1, 2, 3, 10, 1, 2, 3)
>>> c
{1, 2, 3, 10, 11}
>>>

在这个例子中,items 的内容只是粘贴到列表、元组或集合中,就像在该位置键入内容一样。这种扩展称为“泼溅”。定义字面量时,可以根据需要包含任意数量的 * 扩展。但是,许多可迭代对象(例如文件或生成器)仅支持一次迭代。如果你使用 * 扩展,内容将被消耗,并且迭代器不会再产生任何内容后续迭代中的值。

各种内置函数都接受任何可迭代对象作为输入。下表列出了一些这些操作。

函数描述
list(s)从 s 创建一个列表
tuple(s)从 s 创建一个列表
set(s)从 s 创建一个 Set
min(s [,key])s 中的最小项
max(s [,key])s 中的最大想
any(s)如果 s 中的任一项为真,则返回 True
all(s)如果 s 中的所有项为真,则返回 True
sum(s [, initial])所有项的总和,带有一个可选的初始值
sorted(s [, key])创建一个排序列表

序列操作

序列是一个可迭代的容器,具有一定的大小,并允许通过从 0 开始的整数索引,比如说字符串、列表和元组。除了所有涉及迭代的运算,下表中的运算符可以应用于序列。

操作符描述
s + r连接
s * n, n * s将 s 赋值 n 次,其中 n 是整数
s[i]索引
s[i:j]切片
s[i:j:stride]拓展的切片
len(s)求长度

+ 运算符连接两个相同类型的序列。例如:

>>> a = [1, 2, 3]
>>> b = [4, 5]
>>> a + b
[1, 2, 3, 4, 5]
>>>

s * n 运算符制作序列的 n 个副本。然而,这些都是浅拷贝,仅通过引用复制元素。考虑以下代码:

>>> a = [3, 4, 5]
>>> b = [a]
>>> c = 4 * b
>>> c
[[3, 4, 5], [3, 4, 5], [3, 4, 5], [3, 4, 5]]
>>> a[0] = -7
>>> c
[[-7, 4, 5], [-7, 4, 5], [-7, 4, 5], [-7, 4, 5]]
>>>

请注意对 a 的更改如何修改列表 c 的每个元素。在本例中,对列表 a 的引用被放置在列表 b 中。复制 b 时,创建了四个对 a 的附加引用。最后,当 a 被修改时,此更改会传播到 a 的所有其他副本。这种序列乘法的行为通常不是程序员的意图。解决该问题的一种方法是通过复制 a 的内容来手动构建复制序
列。这是一个例子:

a = [3, 4, 5]
c = [list(a) for _ in range(4)]

负索引可用于从序列末尾获取字符。尝试访问超出范围的元素会导致 IndexError 异常。允许使用负索引,并假定为相对于序列的结尾。

>>> a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> a[2:5]
[2, 3, 4]
>>> a[:3]
[0, 1, 2]
>>> a[-3:]
[7, 8, 9]
>>> a[::2]
[0, 2, 4, 6, 8]
>>> a[::-2]
[9, 7, 5, 3, 1]
>>> a[0:5:2]
[0, 2, 4]
>>> a[5:0:-2]
[5, 3, 1]
>>> a[:5:1]
[0, 1, 2, 3, 4]
>>> a[:5:-1]
[9, 8, 7, 6]
>>> a[5::1]
[5, 6, 7, 8, 9]
>>> a[5::-1]
[5, 4, 3, 2, 1, 0]
>>> a[5:0:-1]
[5, 4, 3, 2, 1]
>>>

复杂的切片可能会导致代码在之后难以理解。切片可以使用 slice() 来命名。

>>> first_five = slice(0, 5)
>>> s = "hello world"
>>> print(s[first_five])
hello
>>>

可变序列操作

列表或其他可变序列可以使用下表中的运算符进行就地修改。

OperationDescription
s[i] = x索引赋值
s[i:j] = r切片赋值
s[i:j:stride] = r拓展切片赋值
del s[i]删除一个元素
del s[i:j]删除切片
del s[i:j:stride]删除切片拓展

s[i] = x 运算符更改序列的元素i以引用对象 x,增加 x 的引用计数。负索引相对于列表的末尾和尝试为超出范围的索引分配值会导致 IndexError 异常。切片赋值运算符 s[i:j] = r 将元素 k(其中 i <= k < j)替换为元素来自序列 r。索引与切片的含义相同。如有必要,序列可以扩大或缩小尺寸以容纳 r 中的所有元素。

>>> a = [1, 2, 3, 4, 5]
>>> a[1] = 6
>>> a
[1, 6, 3, 4, 5]
>>> a[2:4] = [10, 11]
>>> a
[1, 6, 10, 11, 5]
>>> a[3:4] = [-1, -2, -3]
>>> a
[1, 6, 10, -1, -2, -3, 5]
>>> a[2:] = [0]
>>> a
[1, 6, 0]
>>>

切片赋值可以提供可选的步长参数。但是,那行为会受到更多限制,因为右侧的参数必须完全具有与被替换的切片具有相同数量的元素。

>>> a = [1, 2, 3, 4, 5]
>>> a[1::2] = [10, 11]
>>> a[1::2] = [30, 40, 50]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: attempt to assign sequence of size 3 to extended slice of size 2
>>>

del s[i] 运算符从序列中删除元素 i,并减少其引用计数。del s[i:j] 删除切片中的所有元素。步长也可以提供,如 del s[i:j:stride] 中所示。

此处描述的语义适用于内置列表类型。涉及序列切片是第三方包中可供定制的丰富领域。你可能会发现非列表对象上的切片在重新分配、删除和删除方面有不同的规则对象共享。例如,流行的 numpy 包具有不同的切片语义比 Python 列表。

Set 操作

Set 是唯一值的无序集合。下表的操作可以在 Set 上执行:

OperationDescription
s | ts 和 t 的并集
s & ts 和 t 的交集
s – ts 和 t 的差集
s ^ t对称差(并集-交集)
len(s)集合中的项数
item in s, item not in s成员检查
s.add(item)添加一个项
s.remove(item)如果存在项,则移除,否则报错
s.discard(item)删除一个存在的项
>>> a = {"a", "b", "c"}
>>> b = {"c", "d"}
>>> a | b
{'a', 'b', 'c', 'd'}
>>> a & b
{'c'}
>>> a - b
{'a', 'b'}
>>> b - a
{'d'}
>>> a ^ b
{'a', 'b', 'd'}
>>>

集合操作也适用于字典的键视图和项目视图对象。例如,为了要找出两个字典有哪些共同的键,请执行以下操作:

>>> a = {"x": 1, "y": 2, "z": 3}
>>> b = {"z": 3, "w": 4, "q": 5}
>>> a.keys() & b.keys()
{'z'}
>>>

映射操作

映射是键和值之间的关联。内置的 dict 类型就是一个例子。下表中的操作可以应用于映射。

OperationDescription
x = m[k]通过键来索引
m[k] = x通过键来赋值
del m[k]通过键来删除一项
k in m成员检查
len(m)映射的项目数
m.keys()返回键的视图
m.values()返回值的视图
m.items()返回键值对的视图

键值可以是任何不可变的对象,例如字符串、数字和元组。当使用元组作为键,可以省略括号并写入逗号分隔的值:

>>> d = {}
>>> d[1, 2, 3] = "foo"
>>> d[1, 0, 3] = "bar"
>>> d
{(1, 2, 3): 'foo', (1, 0, 3): 'bar'}
>>>

使用元组作为键是创建组合键的常用技术。

  • 31
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值