本章主要介绍Python经常使用的数据结构和以及Python函数等基础知识。python
元祖是一种固定长度、不可变的Python对象序列数据结构
建立元组的方法:app
In [3]: tup1 = 1, 2, 3 # 直接 In [4]: tup2 = (1, 2, 3), (4, 5) # 用括号分割 In [5]: tup3 = tuple([1, 2, 3]) # 利用tuple函数将任意序列或迭代器进行转化 In [6]: print(tup1, tup2, tup3) (1, 2, 3) ((1, 2, 3), (4, 5)) (1, 2, 3)
元组一旦建立其各个位置上的对象没法被修改。可是假如元组中的对象是可变的,即可以对其进行修改,eg:列表函数
In [15]: tup = tuple([[1,2], [3]]) In [16]: tup Out[16]: ([1, 2], [3]) In [17]: tup[0].append(4) In [18]: tup Out[18]: ([1, 2, 4], [3])
能够用+
号链接元组来生成更长的元组。atom
若是将元组型的表达式赋值给变量,Python会对等式右边的值进行拆包:设计
In [21]: tup = (1, 2, 3) In [22]: a, b, c = tup # 简单拆包 In [23]: print(a, b, c) 1 2 3 In [24]: tup1 = 4, 5, (6, 7) In [25]: a, b, (c, d) = tup1 # 嵌套元组也行 In [26]: print(a, b, c, d) 4 5 6 7
使用这个功能,可以轻松的实现交换变量名:rest
In [27]: a, b = 1, 2 In [28]: print(a, b) 1 2 In [29]: a, b = b, a # 进行交换 In [30]: print(a, b) 2 1
更为高级的拆包功能,“*rest
用于在函数调用时获取任意长度的位置参数列表”rest变量名并非保留字,能够替换。有时rest部分表明想要丢弃的数据,所以也能够用_
下划线表明不想要的变量:code
In [32]: a, b, *rest = val In [33]: print(a, b, rest) 1 2 [3, 4, 5, 6]
元组方法不多,常见能够使用的是count,用于统计某元素在元组中出现的次数。orm
Note:remove方法会定位第一个符合要求的值并移除它。(区别于C++)对象
使用 in 和 not 能够用于检查一个值是否在列表中。
可是与字典,集合相比检查列表是一个很是缓慢的过程,这是由于 Python 的手段是逐项检查。而在字典和集合中 Python 是同时检查全部元素(基于哈希表)。
在尝试进行列表链接在一块儿时,extend 是比 + 更高效的办法。
内建的 bisect 模块实现了二分搜索和已排序列表的插值。
bisect.bisect
会找到当前元素应当被插入的位置,并保持序列排序。bisect.insort
将元素直接插入到对应的位置。In [63]: arr = [1, 2, 2, 2, 3, 4, 7] In [64]: bisect.bisect(arr, 2) #二分查找 Out[64]: 4 In [65]: bisect.bisect(arr, 5) Out[65]: 6 In [66]: bisect.insort(arr, 6) # 直接插入 In [67]: arr Out[67]: [1, 2, 2, 2, 3, 4, 6, 7]
能够发现bisect.bisect
在有重复元素时指向的是最右边的元素。所以在列表中存在重复元素时,能够考虑以下几个方法:
bisect.bisect_left
bisect.insort_left
bisect.bisect_right
bisect.insort_right
注意bisect方法并不会检查序列是否有序(开销过大),所以在使用前必定要排序(否则会出现错误答案)
切片为 [start : stop] 并不包括最后一个 stop 位置。所以切片的元素长度为 stop - start
负数表明从后往前
切片还有一种语法为:[start : stop : step]
其中 step 表明没过多少步值取一个数,负数表明从后往前取。
In [72]: arr Out[72]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] In [73]: arr[::2] Out[73]: [0, 2, 4, 6, 8] In [74]: arr[::-2] Out[74]: [9, 7, 5, 3, 1] In [75]: arr[::-1] # 实现了翻转 Out[75]: [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
Python 中有许多序列函数,应当认真熟悉
咱们有时须要遍历一个序列的同时追踪当前元素的索引,面对这种场景咱们能够使用Python 内建的 enumerate 函数,返回 (i, value) 元组的序列。例如:
In [78]: for i, val in enumerate(arr): ...: print("{0:d}, {1:d}".format(i, val)) 0, 0 1, 1 2, 2 3, 3 4, 4 5, 5 6, 6 7, 7 8, 8 9, 9
zip 能够处理任意长度的序列,它生成列表的长度由最短的序列决定。
要记住 reversed 是一个生成器(后面详细介绍),只有实体化(即列表或for循 环)以后才能建立翻转的序列。(?? 不太懂先记录)
能够经过 update 方法将两个字典合并,可是若是有相同的键值,则它的值会被新值覆盖
一般状况下,可能会出现这样的设计,咱们先判断某个值是否存在于字典中假如不存在返回一个默认值:
if key in some_dict: value = some_dict[key] else: value = default_value
例如,如今须要经过首字母将单词分类,在没有预设默认值的状况下得用 if-else 分支:
In [123]: words = ['apple', 'bat', 'bar', 'atom', 'book'] In [124]: by_letter = {} In [125]: for word in words: .....: letter = word[0] .....: if letter not in by_letter: .....: by_letter[letter] = [word] .....: else: .....: by_letter[letter].append(word) .....: In [126]: by_letter Out[126]: {'a': ['apple', 'atom'], 'b': ['bat', 'bar', 'book']}
经过setdefault
能够快速解决这个问题:
for word in words: letter = word[0] by_letter.setdefault(letterm, []).append(word) # 设置默认为list
或者经过内建的defaultdict
类实现默认值设置问题。传递类型或函数以生成每一个位置的默认值:
from collections import defaultdict by_letter = defaultdict(list) # 设置默认类型为list类型(能够设置为其余类型) for word in words: by_letter[word[0]].append(word)
只须要注意几点:值能够是任何 Python 对象,可是键必须是不可变的对象,(整数、浮点型、 字符串)或元组(元组中的对象必须是不可变的)
集合的初始化操做
set([1, 2, 2, 3, 4])
{1, 2, 2, 3, 4}
和字典相似,集合中的元素必须是不可变对象,所以假如想要包含列表元素,须要转化为元组类型。
关于一维推导式,记住如下三个经典的便可:
[expr for val in collection if condition]
dict_comp = {key-expr : value-expr for value in collection if condition}
set_comp = {expr for value in collection if condition}
关于多维嵌套列表推导式,只须要记住:for 表达式的顺序应与你写嵌套 for 循环来代替列表推导式的顺序一致。
函数时对象,能够将函数操做存在一个列表中,直接调用,以下图所示:
In [99]: def f1(x): ...: return x + 5 In [100]: def f2(x): ...: return x ** 2 In [101]: def f3(x): ...: return x * 3 In [102]: func = [f1, f2, f3] In [103]: a = 1 In [107]: for funcs in func: ...: a = funcs(a) In [108]: a Out[108]: 108