流畅的python系列——python数据结构之序列2
Posted tianyafu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了流畅的python系列——python数据结构之序列2相关的知识,希望对你有一定的参考价值。
文章内容接上篇
三、切片
《流畅的python》的第2章中,对于切片的简单用法,只是一带而过:
在 Python 里,像列表(list)、元组(tuple)和字符串(str)这类序列类型都支持切片操作,但是实际上切片操作比人们所想象的要强大很多。
文中,主要讲了切片的3个方面:
1.为什么在python中,切片和区间会忽略最后一个元素(即左闭右开)
2.对象的切片
3.给切片赋值
另外,还提及了多维切片和省略
3.1、为什么在python中,切片和区间会忽略最后一个元素(即左闭右开)
在切片和区间操作里不包含区间范围的最后一个元素是 Python 的风格,这个习惯符合Python、C 和其他语言里以 0 作为起始下标的传统。这样做带来的好处如下。
1.当只有最后一个位置信息时,我们也可以快速看出切片和区间里有几个元素:range(3) 和 my_list[:3] 都返回 3 个元素。
2.当起止位置信息都可见时,我们可以快速计算出切片和区间的长度,用后一个数减去第一个下标(stop - start)即可。
3.这样做也让我们可以利用任意一个下标来把序列分割成不重叠的两部分,只要写成my_list[:x] 和 my_list[x:] 就可以了
3.2、对对象切片
我们还可以用 s[a:b:c] 的形式对 s 在 a 和 b 之间以 c 为间隔取值。c 的值还可以为负,负值意味着反向取值。
也就是说,c为步长。
>>> s = ‘bicycle‘ >>> s[::3] ‘bye‘ >>> s[::-1] ‘elcycib‘ >>> s[::-2] ‘eccb‘
3.3、给切片赋值
如果把切片放在赋值语句的左边,或把它作为 del 操作的对象,我们就可以对序列进行嫁接、切除或就地修改操作。
>>> l = list(range(10)) >>> l [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> l[2:5] = [20, 30] >>> l [0, 1, 20, 30, 5, 6, 7, 8, 9] >>> del l[5:7] >>> l [0, 1, 20, 30, 5, 8, 9] >>> l[3::2] = [11, 22] >>> l [0, 1, 20, 11, 5, 22, 9] >>> l[2:5] = 100 Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: can only assign an iterable >>> l[2:5] = [100] >>> l [0, 1, 100, 22, 9]
四、对序列使用+和*
Python 程序员会默认序列是支持 + 和 * 操作的。通常 + 号两侧的序列由相同类型的数据所构成,在拼接的过程中,两个被操作的序列都不会被修改,Python 会新建一个包含同样类型数据的序列来作为拼接的结果。
划重点就是:
+ 和 * 都遵循这个规律,不修改原有的操作对象,而是构建一个全新的
>>> l = [1, 2, 3] >>> l * 5 [1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3] >>> 5 * ‘abcd‘ ‘abcdabcdabcdabcdabcd‘
五、序列的增量赋值
增量赋值运算符 += 和 *= 的表现取决于它们的第一个操作对象。简单起见,我们把讨论集中在增量加法(+=)上,但是这些概念对 *= 和其他增量运算符来说都是一样的。
+= 背后的特殊方法是 __iadd__ (用于“就地加法”)。但是如果一个类没有实现这个方法的话,Python 会退一步调用 __add__ 。考虑下面这个简单的表达式:
>>> a += b
如果 a 实现了 __iadd__ 方法,就会调用这个方法。同时对可变序列(例如list、bytearray 和 array.array)来说,a 会就地改动,就像调用了 a.extend(b)一样。但是如果 a 没有实现 __iadd__ 的话,a += b 这个表达式的效果就变得跟 a = a+ b 一样了:首先计算 a + b,得到一个新的对象,然后赋值给 a。也就是说,在这个表达式中,变量名会不会被关联到新的对象,完全取决于这个类型有没有实 __iadd__ 这个方法。
总体来讲,可变序列一般都实现 __iadd__ 方法,因此 += 是就地加法。而不可变序列根本就不支持这个操作,对这个方法的实现也就无从谈起。
上面所说的这些关于 += 的概念也适用于 *=,不同的是,后者相对应的是 __imul__。关于 __iadd__ 和 __imul__,第 13 章中会再次提及。
书中的这段原话,揭示了在python中,a += b 和 a = a + b 是有区别的。
六、 排序
list.sort 方法会就地排序列表,也就是说不会把原列表复制一份。
内置函数 sorted,它会新建一个列表作为返回值。这个方法可以接受任何形式的可迭代对象作为参数,甚至包括不可变序列或生成器(见第 14 章)。而不管 sorted 接受的是怎样的参数,它最后都会返回一个列表
两个可选的参数
reverse 和key
reverse这个参数的默认值是False,但如果你把它设置成True,那么,就会以降序的形式输出。
key这个参数表示以什么标准来排序,比如,可以是 key = str.lower,也可以是key = len 等等
七、用bisect来管理已排序的
这个小节没看懂,就不多说了
八、array.array ,memoryview,numpy,collections.deque
array用来存放数字,比list更高效,因为 array.array在底层存储的是字节表述。
另外,数组还提供从文件读取和存入文件的更快的方法,如 .frombytes 和 .tofile。
memoryview能让用户在不复制内容的情况下操作同一个数组的不同切片。是一个内置类
numpy库是一个非常优秀的第三方库,是学习pandas库的基础。
第二章就简单的到这里了,有些知识点我也没怎么看懂,可能将来用到了才会懂吧
以上是关于流畅的python系列——python数据结构之序列2的主要内容,如果未能解决你的问题,请参考以下文章