Built-in Data Structures, Functions,and Files
readme
作为一名初学者来说,使用Jupyter Notebook运行Python代码是一个绝佳选择,真正的做到了代码与笔记的结合,可以完全丢弃枯燥的代码注释。
为了优化笔记显示,下面两行代码可以在有多个输出结果的cell(单元格)中实现运行结果的全部输出:
from IPython.core.interactiveshell import InteractiveShell
InteractiveShell.ast_node_interactivity = 'all' #默认为'last'
重点:下面的代码框有两部分组成,代码和输出结果,中间用**#####
**分隔;一定一定要注意打印命令与输出结果的对应哈!!!
提示:本文比较长,在这里手动添加目录的话就更长了,幸运的是优快云有自动的目录索引,上图一目了然:
3.1 数据结构和序列(Data Structures and Sequences)
3.1.1 元组(Tuple)
tuple是长度固定,不可改变的序列。创建元祖的方法是用逗号:
tup = 4, 5, 6
tup
#####
(4, 5, 6)
如果想要创建一个更复杂的tuple的话,还是要用括号,括号之间还是用逗号:
nested_tup = (4, 5, 6), (7, 8)
nested_tup
#####
((4, 5, 6), (7, 8))
把其他序列或迭代器转换为序列:
tuple([4, 0, 2])
tup = tuple('string')
tup
#####
(4, 0, 2)
('s', 't', 'r', 'i', 'n', 'g')
可以⽤⽅括号访问元组中的元素,序列从0开始
tup[0]
#####
's'
元组中存储的对象可能是可变对象。⼀旦创建了元组,元组中的对象就不能修改了:
tup = tuple(['foo', [1, 2], True])
tup[2] = False
#####
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-6-11b694945ab9> in <module>
1 tup = tuple(['foo', [1, 2], True])
----> 2 tup[2] = False
TypeError: 'tuple' object does not support item assignment
但是如果tuple内部的object是可更改的(比如列表),那么我们可以试着更改一下:
tup[1].append(3)
tup
#####
('foo', [1, 2, 3], True)
用+
来合并多个tuple:
(4, None, 'foo') + (6, 0) + ('bar',)
#####
(4, None, 'foo', 6, 0, 'bar')
*
相当于copy多份,也可以用在list上:
('foo', 'bar') * 4
#####
('foo', 'bar', 'foo', 'bar', 'foo', 'bar', 'foo', 'bar')
3.1.1.1 拆分元组(Unpacking tuples)
Python会试图拆分等号右边的值:
tup = (4, 5, 6)
a, b, c = tup
b
#####
5
即使含有元组的元组也会被拆分:
tup = 4, 5, (6, 7)
a, b, (c, d) = tup
d
#####
7
用下面的方法来交换变量的名字:
tmp = a
a = b
b = tmp
但是在python里,交换能更简洁一些:
a, b = 1, 2
a, b
b, a = a, b
a, b
#####
(1, 2)
(2, 1)
变量拆分常⽤来迭代元组或列表序列:
seq = [(1, 2, 3), (4, 5, 6), (7, 8, 9)]
for a, b, c in seq:
print('a={0}, b={1}, c={2}'.format(a, b, c))
#####
a=1, b=2, c=3
a=4, b=5, c=6
a=7, b=8, c=9
另一种更高级的unpacking方法是用于只取出tuple中开头几个元素,剩下的元素直接赋给*rest
:
values = 1, 2, 3, 4, 5
a, b, *rest = values
a, b
rest
#####
(1, 2)
[3, 4, 5]
rest部分是你想要丢弃的,名字本身无所谓,通常用下划线来代替:
a, b, *_ = values
3.1.1.2 元组方法(Tuple methods)
因为tuple的大小和内容都不能改变,所以方法也很少。count
用来计算某个值出现的次数,list中也有这个方法:
a = (1, 2, 2, 2, 3, 4, 2)
a.count(2)
#####
4
3.1.2 列表(List)
列表的灵活性就很强了,大小和内容都可以变:
a_list = [2, 3, 7, None]
tup = ('foo', 'bar', 'baz')
b_list = list(tup) # 元组转化为列表
b_list
b_list[1] = 'peekaboo' # 替换列表中的第二个元素
b_list
#####
['foo', 'bar', 'baz']
['foo', 'peekaboo', 'baz']
列表和元组的语义接近,在许多函数中可以交叉使⽤。
list
函数常⽤来在数据处理中实体化迭代器或⽣成器:
gen = range(10)
gen # 这是一个迭代器,所以无法看到里面的内容
list(gen) # 实体化后就可以看到了
#####
range(0, 10)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
3.1.2.1 添加和移动元素(Adding and removing elements)
可以⽤append在列表末尾添加元素:
b_list.append('dwarf') # 在b_list中添加一个元素'dwarf'
b_list
#####
['foo', 'peekaboo', 'baz', 'dwarf']
insert
可以在特定的位置插⼊元素:
b_list.insert(1, 'red')
b_list
#####
['foo', 'red', 'peekaboo', 'baz', 'dwarf']
注意:与append
相⽐,insert
耗费的计算量⼤,因为对后续元素的引⽤必须在内部迁移,以便为新元素提供空间。如果要在序列的头部和尾部插⼊元素,可以使⽤collections.deque
,⼀个双尾部队列。
insert
的逆运算是pop
,它移除并返回指定位置的元素:
b_list.pop(2)
b_list
#####
'peekaboo'
['foo', 'red', 'baz', 'dwarf']
remove
可以通过值移除指定的element,如果同一个值在序列中多次出现,只移除第一个:
检查一个值是否在list中,用in:b_list.append('foo')
b_list
b_list.remove('foo')
b_list
#####
['foo', 'red', 'baz', 'dwarf', 'foo']
['red', 'baz', 'dwarf', 'foo']
检查一个值是否在list中,用in
:
'dwarf' in b_list
'dwarf' not in b_list
#####
True
False
3.1.2.2 串联和组合列表(Concatenating and combining lists)
与元组类似,可以⽤+
将两个列表串联起来:
[4, None, 'foo'] + [7, 8, (2, 3)]
#####
[4, None, 'foo', 7, 8, (2, 3)]
通过entend
方法,可以添加多个元素:
x = [4, None, 'foo']
x.extend([7, 8, (2, 3)])
x
#####
[4, None, 'foo', 7, 8, (2, 3)]
注意:用+法来做合并是一个运算量较大的操作,因为要创建一个新的list并复制。如果操作的是一个很大的list,用extend
会更好一些:
#解释性代码
everything = []
for chunk in list_of_lists:
everything.extend(chunk)
串联的方法更快
everything = []
for chunk in list_of_lists:
everything = everything + chunk
总结:
append和extend的区别。
- append是把元素添加到一个list里
- extend是把两个list结合在一起
extend和+
的区别
+
是创建了一个新的list并返回,运算量大- extend是在原本的list上做了更改,运算量小
3.1.2.3 排序(Sorting)
排序用sort函数
a = [7, 2, 5, 1, 3]
a.sort()
a
#####
[1, 2, 3, 5, 7]
sort
函数有一些比较方便的选项。比如设置一个sort key,这个key也是一个函数(funciton)。比如我们想要按string的长度来排序:
b = ['saw', 'small', 'He', 'foxes', 'six']
b.sort(key=len) # 按字符串长度排序
b
#####
['He', 'saw', 'six', 'small', 'foxes']
3.1.2.4 ⼆分搜索和维护已排序的列表(Binary search and maintaining a sorted list)
bisect
模块⽀持⼆分查找,和向已排序的列表插⼊值。bisect.bisect
可以找到插⼊值后仍保证排序的位置,bisect.insort
是向这个位置插⼊值:
import bisect # 加载模块
c = [1, 2, 2, 2, 3, 4, 7]
bisect.bisect(c, 2) # 找2应该插在那个位置
bisect.bisect(c, 5) # 找5应该插在那个位置
bisect.insort(c, 6) # 找6应该插在那个位置,并且把6插进去
c
#####
4
6
[1, 2, 2, 2, 3, 4, 6, 7]
3.1.2.5 切片(Slicing)
[start:stop]
, 输出的结果包含开头,不包含结尾。所以输出的结果的数量是stop-start
seq = [7, 2, 3, 7, 5, 6, 0, 1]
seq[1:5] # 不包括结尾
#####
[2, 3, 7, 5]
可以赋值:
seq[3:<