内置类型与元组、数组、字典、集合,及常用操作。
内置类型
Python 中的内置类型
- None: 全局只有一个.
- 数值类型:int, float, complex 复数类型, bool.
- 迭代类型:迭代器、生成器,可以用 for 循环遍历。
- 序列类型:list, (bytes, bytearray, memoryview), range, tuple, str, array.
- 映射:字典,有 key 和 value
- 集合:set,frozenset(不可修改的 set),set 和 dict 的实现原理差不多,性能很高。
- 上下文管理器:with 语句。
- 其他:模块类型、class 和实例类型、函数类型、方法类型、代码类型、object对象、type类型、ellipsis 类型(省略号), notimplemented类型。
元组
性质
元组内部元素确定以后,不可修改;如果元组里可以放数组,数组的元素是可以修改的,创建一个元组:
1 | tup = 4,5,6 |
嵌套元组:
1 | tup = (4,5,6),(7,8,9) |
其实等于:
1 | tup = ((4,5,6),(7,8,9)) |
任何序列或可迭代的对象都可以转化为元组:
1 | tuple([3,4,5]) |
通过tuple[]这种方式起来访问元组的内容。
元组可以相加,变成一个更长的元组,即a+b = ab;也可相乘,即ab*4 = abababab
解包
如果你尝试将元组赋值给多个变量,Python会尝试把元组拆开分别赋值给这些变量(即解包)。
1 | tup = (1,2,3) |
这时候,a = 1, b = 2, c = 3;
嵌套的元组也是可以的:
1 | tup = (1,2,(3,4)) |
这时候,d = 4;
在别的语言中,如果你要交换两个元素,需要这样操作:
1 | tmp = a |
python里面可以这样
1 | b,a = a,b |
解包还有一些其他的用法,比如按照元组的数据结构解包:
1 | seq = [(1,2,3),(4,5,6),(7,8,9)] |
只提取前面几个元素,后面的放一起:
1 | values = 1,2,3,4,5 |
元组有一个方法,可以统计特定的值在元组中出现的次数:
1 | a = (1,2,2,3) |
命名元组
这部分为高级内容,看不懂的可以跳过。
使用命名元组需要先导入,假设我们有一个故事Stock,里面有股票的名字,股份数量shares,还有股价price,那我们就可以设置一个命名元组如下: 1
2from collections import namedtuple
Stock = namedtuple('Stock', ['name', 'shares', 'price'])
同时我们可以定义一个函数用来计算市值,可以注意到,在这个函数内部,我们创建了一个命名元组对象s,有了这个对象以后,我们就可以直接调用s的shares和price属性: 1
2
3
4
5
6def compute_cost(records):
total = 0.0
for rec in records:
s = Stock(*rec)
total += s.shares * s.price
return total
我们也可以直接这样操作:
1 | apple = Stock('name',100,297) |
需注意这样会报错:
1 | compute_cost('apple',100,297) ---> takes 1 positional argument but 3 were given |
命名元祖创建后不可修改,比如 apple.shares = 10 , 会报错。如果实在要改,可以使用apple = apple._replace(shares=10),如果你的目标是定义一个需要更新很多实例属性的高效数据结构,那么命名元组并不是你的最佳选择。 这时候你应该考虑定义一个包含 slots 方法的类。 # 数组
数组相信大家都不陌生,数组可以包含None值:
1 | a_list = [1,2,None] |
可以从元组转化而来:
1 | tup = ('foo','bar','baz') |
可以按照索引来修改数组的值:
1 | b_list[1] = 'peekaboo' |
list可以直接转化生成器或者迭代器:
1 | gen = range(10) |
添加、删除
使用append方法即可往数组添加元素:
1 | values = ['a','b'] |
也可以使用insert方法向指定的位置插入元素:
1 | values.sert(1,'-') |
insert比append要花费更多的资源,因为insert后,其后面的元素都要挪位置,如果你要在数组的首尾操作,可以去看看collections.deque
相反的,我们可以使用pop方法来取出指定位置的元素, 这时候后面的元素也都会往前面移动:
1 | values.pop(0) # a |
也可以直接根据值来删除某个元素:
1 | values.remove('b') |
检查某个元素是否在数组中:
1 | 'a' in ['a','b','c'] |
在数组是否包含某个元素,比字典和sets要慢的多。
运算
数组的相加,即首尾相连,a+b = ab; 数组的相加需要创建新的数组,还要进行复制运算,所以耗费的资源会比较多,所以我们一般使用extend方法:
1 | ['a']+['b'] # ['a','b'] |
排序
你可以直接排序一个数组,且不需要创建一个新的数组,只需要调用sort方法即可:
1 | a = [7,2,1] |
sort接收第二个参数,可以定义sort的条件,比如我们通过字符的长度来排序:
1 | b = ['saw','small','he','six'] |
二分查找与操作
python内置了一个bisect模块,实现了基于二分查找的算法,在列表中查找元素可以使用 list.index() 方法,其时间复杂度为O(n)。对于大数据量,则可以用二分查找进行优化,二分查找也成为折半查找,算法每一次比较都使搜索范围缩小一半, 其时间复杂度为 O(logn),需要注意,二分查找要求对象必须有序。
1 | c = [1,2,2,2,3,4,7] |
切片
通过将形如start:stoped的格式传给[],就可以在序列对象中切出你想要的部分,举例:
1 | seq = [6,5,3,5,7,2] |
切片也可以赋值,比如:
1 | seq[2:4] = [0,0] |
如果你要选择之前或者之后的所有值,将一边省略即可,比如我要选择index=3之后的所有值,即[3:]。
你甚至可以指定步长,也就是隔多远选一个值,例如:
1 | seq = [6,5,3,5,7,2] |
如果你想将数组反转,将步长设为-1试试:
1 | seq = [6,5,3,5,7,2] |
内置的序列函数
enumerate
在用for in循环一个序列的时候,我们经常想要跟踪index,为此你可能会声明一个i来记录:
1 | i = 0 |
不过python已经内置了一个函数,可以帮到你:
1 | for index,value in enumerate(['a','b','c']): |
这里的index就是你想要的那个i了。enumerate在将列表转化为字典的时候尤其方便:
1 | some_list = ['for','bar','baz'] |
sorted
sorted函数接收一个序列对象,排序后返回一个新的。
zip
zip会将两个序列中的元素一一对应。
1 | seq1 = ['scott','frank','jason'] |
zip可以接受3个序列一一对应,对应关系按照最短的处理。
将如上函数结合,可以实现一些很骚的写法,看下面的例子,将序列结合并按顺序打印: 1
2
3for i (a,b) in enmerate(zip(se1,seq2)):
print('{}:{},{}'.format(i,a,b))
统计名和姓:
1 | pitchers = [('Nolan', 'Ryan'), ('Roger', 'Clemens'),('Schilling', 'Curt')] |
reversed
1 | list(reversed(range(10))) |
reversed返回一个生成器,如果你想要取出其中数据,需要用list包装一下。
字典
字典是python中最重要的数据结构之一,创建dict很简单,直接使用花括号就创建了一个dict。
1 | d = {} |
增加元素:
1 | d[1] = 'hi' |
检查字典中是否有某个key(检查的不是values,而是key)
1 | 1 in d |
删除字典中的值,可以用del命令,或者pop方法:
1 | d = {} |
pop方法会返回删除的元素。
可以直接使用d.keys(),和d.values()方法访问dict的所有keys和values。
使用d.update()方法,可以将两个dict合并。
从两个序列创建一个字典,你也许会准备一个index列表和values列表,再用for循环手动创建,大可不必。你可以直接使用dict+zip函数来定义:
1 | mapping = dict(zip(indexs,values)) |
默认值
检测dict是否拥有某个值,如果有就取出来,没有就设置默认值,这应该是很常用的操作了,为此你可能会写如下的代码:
1 | if key in some_dict: |
使用dict内置的get方法,可以让你的代码更简洁:
1 | value = some_dict.get(key,default_value) |
如果你有一堆字符串需要按照首字母分类,你可能会这样写:
1 | words = ['apple','bat','bar','atom','book'] |
借助dict的setdefault方法,可以让你的代码更简洁:
1 | words = ['apple','bat','bar','atom','book'] |
key的类型
字典的值可以是任何python的对象,而key则不行,必须是不可变类型,你可以用hash函数去检测,如果能返回值,说明它可以作为字典的key,如果报错就不行:
1 | hash('string') # ok |
如果一定要list作为键,可以先将它转化成元组。
1 | d = {} |
字典高级用法
collection模块对字典也提供了很多方便的方法:
多个字典遍历
1 | from collections import ChainMap |
字典合并
1 | a = {'x': 1, 'z': 3 } |
集合
集合是没有顺序关系的元素放在一起。你可以想象成是字典中,只有key,没有值。字典的创建有两种方式:
1 | set([1,2,3,4]) |
集合支持数学层面的运算,比如交集、并集等。
1 | a ={1,2,3,4,5,6,7,8} |
更多的运算规则可以去网上查查看。