List & Tuple
基础概念
列表和元祖都是一个可以放置任意数据类型的有序集合,在大多数语言中,集合中的数据类型必须一致,但python并不做强制要求形态不同列表为动态,可以修改,长度不固定
元祖是静态,不可更改,长度固定
存储不同列表是动态的,其需要指针来存储,通过指针指向对应的元素,由于列表可变,需要额外存储已经分配的长度大小(8 字节),这样才可以实时追踪列表空间的使用情况,空间不足时,及时分配额外的空间,这样保证了其高效的操作性,增加/删除的时间复杂度均为O(1)。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18l = []
l.__sizeof__() // 空列表的存储空间为 40 字节
40
l.append(1)
l.__sizeof__()
72 // 加入了元素 1 之后,列表为其分配了可以存储 4 个元素的空间 (72 - 40)/8 = 4
l.append(2)
l.__sizeof__()
72 // 由于之前分配了空间,所以加入元素 2,列表空间不变
l.append(3)
l.__sizeof__()
72 // 同上
l.append(4)
l.__sizeof__()
72 // 同上
l.append(5)
l.__sizeof__()
104 // 加入元素 5 之后,列表的空间不足,所以又额外分配了可以存储 4 个元素的空间+ 元祖因为静态,长度固定,所以存储空间固定性能不同因为Python的后台资源缓存以及垃圾回收机制,对于元祖这类的静态变量,如果占用空间不大,Python会暂时缓存这部分内存,这样重新创建时,可以直接分配之间缓存的内存空间,加快程序运行。
都支持索引(包括负索引),速度上无明显差别
使用场景不同元祖更适合存储固定的数据,如返回经纬度,给前段渲染
列表更适合动态数据,如用户浏览记录,日志等时常需要更新的
相互之间可以所以嵌套,无固定形式要求
通过list()和tuple()可以相互转换
基础操作
内置函数1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29l = [3, 2, 3, 7, 8, 1]
#统计item出现的次数
l.count(3)
2
#返回第一次出现的索引
l.index(7)
3
#原地翻转,元祖内无此函数
l.reverse()
l
#排序,元祖内无此函数
[1, 8, 7, 3, 2, 3]
l.sort()
l
[1, 2, 3, 3, 7, 8]
tup = (3, 2, 3, 7, 8, 1)
tup.count(3)
2
tup.index(7)
3
#reversed() 和 sorted()与上述功能相同,
#但reversed()返回的是一个反转的迭代器
list(reversed(tup))
[1, 8, 7, 3, 2, 3]
sorted(tup)
[1, 2, 3, 3, 7, 8]
Dict和Set
基础概念
Dict是一系列key和value配对组成的元素的集合,在python3.6中,字典并非有序,而3.7中正式成为语言特性,确定为有序,相对于列表和元祖,字典在查找、添加和删除操作,字典都能在常数时间复杂度内完成。
集合和字典基本相同,元素没有键值配对,一些列无需且唯一的元素
基础操作
访问
字典访问可以直接访问键,获取值,如果不存在,就会发出异常,可以采用ge他(key,default)函数来索引,如果键不存在,会返回null,并不会抛出异常1
2
3
4
5d = {'name': 'jason', 'age': 20}
d.get('name')
'jason'
d.get('location', 'null')
'null'
增删改查
集合并不支持索引操作(否则会抛出异常),其本质属于一个哈希表,与列表不同。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23#dict的增删改查
d = {'name': 'jason', 'age': 20}
d['gender'] = 'male' # 增加元素对'gender': 'male'
d['dob'] = '1999-02-01' # 增加元素对'dob': '1999-02-01'
d
{'name': 'jason', 'age': 20, 'gender': 'male', 'dob': '1999-02-01'}
d['dob'] = '1998-01-01' # 更新键'dob'对应的值
d.pop('dob') # 删除键为'dob'的元素对
'1998-01-01'
d
{'name': 'jason', 'age': 20, 'gender': 'male'}
#集合的增删改查
s = {1, 2, 3}
s.add(4) # 增加元素 4 到集合
s
{1, 2, 3, 4}
s.remove(4) # 从集合中删除元素 4
s
{1, 2, 3}
#集合的pop操作是删除集合中的最后一个元素,但因其本身是无序的,无法知道会删除哪个元素,需谨慎使用
s.pop()
排序
字典返回的是列表,内部是键值组成的元祖,1
2
3
4
5
6
7
8
9
10
11
12
13#字典
d = {'b': 1, 'a': 2, 'c': 10}
d_sorted_by_key = sorted(d.items(), key=lambda x: x[0]) # 根据字典键的升序排序
d_sorted_by_value = sorted(d.items(), key=lambda x: x[1]) # 根据字典值的升序排序
d_sorted_by_key
[('a', 2), ('b', 1), ('c', 10)]
d_sorted_by_value
[('b', 1), ('a', 2), ('c', 10)]
#集合
s = {3, 4, 2, 1}
sorted(s) # 对集合的元素进行升序排序
[1, 2, 3, 4]
性能
字典和集合内部存储的结构为高度优化的hash列表,无论是插入还是查找,都以hash值作为坐标,因此大大减少时间复杂度。
Str
拼接1
2
3
4
5
6
7
8
9
10#拼接列表中的数据成一个字符串
In [1]: li = [1, 'kems', 'is', 'liangzai']
In [2]: ''.join([str(i) for i in li])
Out[2]: '1kemsisliangzai'
#当列表内容过多时,可以使用生成器表达式
In [3]: ''.join(str(i) for i in li)
Out[3]: '1kemsisliangzai'
拆分1
2
3
4
5In [5]: s = "ab;fd/ft|fs,f\tdf.fss*dsf;df:ss}ddd"
#实际操作中,可以先遍历字符串,取出其中所含的分隔符
#然后切分
In [6]: print(re.split('[;/|,.}:*\t]', s))
['ab', 'fd', 'ft', 'fs', 'f', 'df', 'fss', 'dsf', 'df', 'ss', 'ddd']
判断字符串的开头和结尾1
2str.startswith()
str.endswith()
调整字符串中文本的格式1
2
3#替换日期 将美国日期格式'mm/dd/yyyy'.比如 2019-06-12 改成 06/12/2019 格式
print(re.sub('(\d{4}) - (\d{2}) - (\d{2})'), r'\2/\3/\1', text)
删除字符串中不需要的字符1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23#过滤掉用户输入中前后多余的空白字符:“ nick2008@gmail.com ”
In [8]: ss = " nick2008@gmail.com "
#去除两端的空格
In [9]: ss.strip()
Out[9]: 'nick2008@gmail.com'
#去除左边的空格
In [10]: ss.lstrip()
Out[10]: 'nick2008@gmail.com '
#去除右边的空格
In [11]: ss.rstrip()
Out[11]: ' nick2008@gmail.com'
#过滤掉某 windows 下编辑文本中的 “\r” :“hello world \r\n”
In [14]: sss = "helloworld\r\n"
In [15]: re.sub("\r", "", sss)
Out[15]: 'helloworld\n'
In [16]: sss.replace("\r", "")
Out[16]: 'helloworld\n'
#去掉文本中的 unicode 组合符号(音调):nǐ hǎo mā