Python数据结构 Python data structure


python 序列

包括字符串,列表,元组,range对象,字典,集合等数据类型

补充记忆知识点**整数数据类型:

0b开头代表二进制 如:0b1001

0o开头代表八进制 如:0o527

0x开头代表十六进制 如:0xff5a

浮点数中的科学记数法:3.14e-2(即为0.0314)

注意科学计数法幂次必须是整数

0.序列概述

0.0常用内建函数

**int()**将一个字符串或数字暴力转换为整型,即浮点数去除小数点变为整数。

chr()可将整数转换成其作为ASCII码对应的字符
**ord()**可将字符转换成其对应的ASCII码

len()可以返回序列的长度

sum()可以返回数字序列中所有数字的和

max/min()可以返回序列对象的最大/最小值,通过key确定排序方式

list()可以强制将可迭代对象转换为列表

tuple()可以强制将可迭代对象转换为元组

str()操作可迭代对象,则会把可迭代对象整体表达转为字符串,输入迭代器会直接把迭代器存储空间转为字符串。

总之就是可迭代对象打印出来什么样子,str就把它转为什么样的字符串。

eval()与前者功能恰好相反,它可以把字符串格式的表达式求值返回。更广义上来说,eval()函数可以把一段字符串转为可执行的代码。常用于文件读取后执行其中的内容。

eval()还可以用于输入字符串快速转为int格式赋值给变量

1
2
3
4
5
6
7
8
9
10
11
12
>>> print(str((1,2,3,4)))
>>> "(1,2,3,4)"
>>> a=str(zip('123','abc'))
>>> print(a)
>>> '<zip object at 0x000002446CDA2708>'
>>> x=7
>>> eval('3*x')
>>> 21
>>> n1, n2 = eval(input("input two numbers a, b: "))
>>> input two numbers a, b: 0,1
>>> print(n1,n2,sep=' ')
>>> 0 1

range(start,end,step) 生成一个整数数列,start可以取到,end不能取到(Python的特征),step默认为1,-1则为倒序生成数列。

help函数调用时内部函数无需带括号,如:help(‘list.sort’)

0.1基本输入输出函数

输入函数

input(“提示语句”),返回输入的字符串。

如果要将一次性输入的多个数字转为列表进行后续操作,一般使用如下代码:

1
a=list(map(int,input("请输入几个数字,以空格间隔").split(" ")))

解析:用户字符串先输入input函数,然后对字符串进行split方法,以空格为间隔符拆分,用map函数映射批量转整型数字,然后把迭代器转为list列表存储。

输出函数

print()函数可以自由地输出各种序列,并且可以在不同序列之间插入字符串连接。

默认每次进行print()函数后,都会自动连接一个**换行符”\n”**。如果不想下次输出换行,则可以设置end参数:

print(“ “,end=””)则强制将结尾符由/n改为空字符。如果下次输出想要间隔,则可以设置end=“ ”

format格式化模板

格式化输出模板:print(“dviding {} by {}”.format(对象0, 对象1….对象n))

若在{}中输入数字,则为对象的索引,可以按索引填充字符串。

除此之外,格式化模板提供格式符,可以在{}中输入统一格式:

{序号:【对齐说明符】【符号说明符】【最小宽度说明符】【.】【精度说明符】【类型说明符】}

例如:{0:#>6.2f} 代表序号为0,右对齐并以#填充空格,输入最小长度为6位,2位小数,浮点数类型

1
2
>>> print("输出结果为 {0:#>6.2f}".format(3.1415926))
>>> ##3.14

【对齐说明符】:^居中对齐;<左对齐;>右对齐

【类型说明符】:f浮点小数;e科学记数法;%百分数;d十进制;x十六进制;o八进制;b二进制

0.2可迭代对象的映射批处理

map(f, iterable):接受一个函数f和一个可迭代对象并通过将f依次作用在可迭代对象的每一个元素上得到一个新的迭代器对象(需要通过list等方法转化为列表等形式,但是不能用str()直接转字符串,需要用str=’’.join(迭代器))。
应用举例:将输入的字符串列表转化为整数列表

0.3赋值、浅拷贝与深拷贝

赋值:b=a

是直接把b的内存空间指向a,两者完全公用一个内存空间,一荣俱荣,一损俱损。他们之间存在着不可磨灭的纽带,修改其中任何一个,另外一个也会跟着变化。

浅拷贝时,内部复杂元素仍使用同一内存空间,一个发生更改,其他也会跟着一起变化。因此容易出现易忽视的未知bug。

1
2
3
4
5
6
7
>>> a=[1,2,[3,4]]
>>> b=a.copy()
>>> b[0],b[2][0]=5,5
>>> print(a)
>>> [1,2,[5,4]]
>>> print(b)
>>> [5,2,[5,4]]

在此案例中,列表内部嵌套的列表在拷贝后仍然使用同一内存空间,因而b的[3,4]变更为[5,4]时,a对应位置的[3,4]也变更为[5,4]。

如果不想因为浅拷贝同内存空间导致变量牵连,应使用深拷贝,开辟完全独立的新内存空间,互不干扰:

1
2
3
4
5
>>> import copy
>>> a=[1,2,[3,4]]
>>> b=copy.deepcopy(a)
>>> print(b)
>>> [1,2,[3,4]]

0.4 序列的通用操作

索引

从左往右数,序列的索引为0,1,2,3,4,……..(与实际日常排序比,均少1,因为第一个元素的索引是0)

另外还支持负数索引:……-4,-3,-2,-1,最后一个数的索引为-1.从右往左数

索引的使用为[]方括号,例如:序列[index]

切片

序列索引的升级版,可以设置初始位置索引和终止位置索引,再设置一个步长。

格式也是方括号:序列[strat : end : step]

重复

对序列使用乘法符号,则重复序列并连接为更长的序列。

1
2
>>> ‘Python’*2
>>>'PythonPython'

连接

同类型序列用加法符号可以直接连接。此处不再赘述,详情见str节的连接字符串部分。

排序

sorted(iter,key,reverse)

内置函数,可以把任意序列iter中的元素强制排序,并转化为列表返回。注意这种方法的返回对象是列表,而非迭代器或者别的。

可选参数key可以指定排序方式,而reverse控制排序的正反向。

key=str/lambda表达式

​ 按长度排序:key=lambda x:len(x)

​ 按列表内置元组第三个元素排序:key=lambda s: s[2]

倒序:reverse=True

1
2
3
>> students = [('john', 'A', 15), ('jane', 'B', 12), ('dave', 'B', 10)]
>>> sorted(students, key=lambda s: s[2]) # 按年龄排序
>>> [('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]

也常用于字典的排序。可以先用dict.keys()或dict.values()提取出键或者值进行排序,也可以用dict.items同时提取键值对,再用key加lambda匿名函数指定按键还是值排序:

1
2
3
4
5
6
7
>>> dict={'a':2,'b':3,'c':1}
>>> sorted(dict.keys())
['a', 'b', 'c']
>>> sorted(dict.values())
[1, 2, 3]
>>> sorted(dict.items(),key=lambda x:x[1],reverse=True)
[('b', 3), ('a', 2), ('c', 1)] #按值倒序排列

0.5 可修改与不可修改类型

基本概念

可修改:list, dict, set, 大部分自定义类型,前三种可以用解析方法创建

不可修改: int,bool,float,tuple,str,frozenset

本质:不可变的是每一个元组元素到实际对象(值)的引用/绑定关系

对运行效率的影响

对于不可变类型反复修改时会反复创建新对象,降低运行效率。

0.6 迭代器对象与可迭代对象

迭代器对象

指向可迭代对象中某个位置,通过next()函数访问下一个位置的元素,直到没有元素抛出StopIteration

相当于使用时指针向后移动,移动到末尾则迭代器任务完成,无法继续使用。

可迭代对象

通过iter()函数或self.__iter__()返回一个迭代器对象

区别

迭代器只能用一次:

1
2
3
4
5
>>> x = iter([1, 2, 3])
>>> print(list(x))
>>> [1, 2, 3]
>>> print(list(x))
>>> []

生成迭代器对象的函数

倒序

reversed()函数返回倒向排序的迭代器对象,需用list()等转化为相应所需形式

1
2
3
4
5
>>>x=[a,b,c,d]
>>>reversed(x)
>>> <list_reverseiterator object at 0x0000000002FA0448>
>>>list(reversed(x))
>>>[d,c,b,a]

枚举

enumerate()函数用于枚举可迭代对象中的元素,返回迭代器对象,每个元素都是一个包含索引和值的元组

1
2
3
4
>>> x=enumerate('abcd')
>>> <enumberate object at 0x0000000002FA0448>
>>> list(x)
>>> [(1,'a'),(2,'b'),(3,'c'),(4,'d')]

压缩

zip(a,b)函数像一个拉链,将多个可迭代对象的对应位置元素组合为一个元组,返回一个迭代器对象

当多个输入的可迭代对象长度不同时,以最短的进行匹配。

1
2
3
4
>>> x=zip('abcd','123')
>>> <enumberate object at 0x0000000002FA0448>
>>> list(x)
>>> [('a','1'),('b','2'),('c','3')]

映射

map(f, iterable)函数用于将某个函数一一映射到序列上进行操作,返回一个迭代器对象

常用于字符串拆分后批量转int数字,来获取一次输入多个值形成列表。

1
2
3
>>> a=list((map(int,input().split(',')))
>>> 1,2,3
>>> [1,2,3]

1.列表List [ ]

1.1列表的方法

1)类似数组利用下标赋值

2)添加元素:

list.append(obj):

​ 在列表结尾添加新元素
list.insert(index, obj):

​ 在列表中某一位置插入元素,插入后下标为index,若index过大则插在最后

3)删除元素:

list.pop(index):

​ 删除列表中下标为index的元素,不写index默认删除最后一项并返回删除元素的值(pop:弹出)

list.remove(obj):

​ 删除列表中等于obj的元素

4)列表反序:

list.reverse():

与内建函数reversed(list)不同:使用list.reverse()方法,则会直接反序原列表,因为列表是可变对象。

5)列表排序

list.sort(key=None/len/str , reverse=True/False):

与内建函数sorted(list)不同:使用list.sort()方法,则会直接排序原列表,但这样做会覆盖原列表。

1.2列表使用

1.成员判断(in),序列连接(+),序列重复(*)
2.整体操作:
list.sort(),list.reverse(),list.extend(iterable)(将可迭代对象分割为列表并合并入原列表),其返回值均为none,只修改原列表;
sorted(list)返回新列表,reversed(list)返回反转列表的迭代器,len(list)返回列表元素个数。

3.list.count()可用于计数

4.list.index()可用于查找(列表没有find方法),list.clear()可用于清空列表。

5.统计操作:max(list), sum(list)

1.25 列表比较

列表的值比较结果为其逐元素比较的结果:

1
2
3
4
5
6
a = [1, 2, 3, 4, 5]
b = [1, 2, 3, 4, 5]
>>> a == b
>>> True
>>> a is b
>>> False

1.3创建列表

列表解析

列表解析:利用循环生成列表的一种简洁方式
公式:newlist = [expression1 for item1 in iterable1 for item2 in iter2 … if condition == True else exp2]
可以有多个for语句,从左到右依次执行(相当于嵌套循环)
可以有复杂的条件判断表达式(if-else)

其他方法

关于高维列表:list(zip(*matrix))可以直接返回转置后的矩阵
列表切片:newlist = listA[start : end : step],其中start到end为左闭右开区间
若start、end为负数则为倒数第x个,但此时step仍默认为1不是-1
列表复制:copy浅拷贝,deepcopy深拷贝
可通过list()将range对象、字符串、可迭代对象转化为列表。

创建多维列表:alist = [[]]*n可以创建一个n行矩阵

2.字符串String “ “

list等可迭代对象和str的转化:x.join(iterable),将list等可迭代对象中的元素用字符串x拼接起来
例:’’ ‘’.join(reversed(astr))

字符串是不可变对象,因而字符串使用字符串对象的方法进行操作,格式为str.方法名(),涉及“修改”字符串则是通过对应方法返回修改后的新字符串。若确实想修改原字符串,则可用赋值语句:

str=str.方法名()

str =”” .join(函数名(Str))—函数返回的可迭代对象通过join组合为字符串,不能直接str(可迭代对象)。并且迭代器输出的值也必须是字符串类型,不能是其他类型的数据(如列表拆分出的int)。

不可使用索引直接修改字符串中的某一部分。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
>>> Str="abcde"
>>> Str[1]
>>> 'b'
>>> Str[1]=c
>>> Traceback (most recent call last):
File "<pyshell#2>", line 1, in <module>
Str[1]=c
NameError: name 'c' is not defined
----------------------------------------------------------------------------
>>> Str="abcde"
>>> Str=Str.upper()
>>> Str
>>> 'ABCDE'
----------------------------------------------------------------------------
>>> Str="abcde"
>>> Str=''.join(reversed(Str))
>>> Str
>>>'edcba'

2.0 字符串的表示

  1. str’1’ng1: “str’1’ng1”
    也可以用’str”i”ng’表示内部有引号的字符串

  2. 三引号可以在字符串中换行,输出时也换行,换行即为一个换行符\n

    1
    2
    3
    4
    >>> a='''abc
    12\t3'''
    >>> print(len(a))
    >>> 8

2.1查找/计数

str.find()rfind()

​ 查找指定字符串在指定范围内首次出现的位置,返回被查找对象的索引数字。如用rfind()则倒序查找返回最后一次出现的位置

str.index()rindex()

​ 与find()基本一致,但index方法找不到直接报错,find方法找不到返回-1
str.count():

​ 统计特定字串出现个数
str.startswith/endswith():

​ 判断字符串是否由特定字串开始/结束,返回布尔值

2.2切分

str.split():

​ 将字符串按照特定字串分割为新的字符串列表,不包含给定字串
str.partition/rpartition():

​ 将字符串按照特定字串分割为新的三元字符串元组返回(左切片,字串,右切片),左切片和右切片全部合并为一整个字符串,如使用rpartition()则从右向左搜索分割字串。

2.3替换

str.replace(old, new, maxnum):

​ 将字符串中的old字串替换为new字串,可设置最大替换次数,返回新字符串
注意:若要替换单词,如果不将目标字串两端加空格的话包含该字串的单词中的字串也会被替换

2.4调整/判断大小写

str.upper/lower():

​ 将字符串中所有字母全部转化为大/小写;

str.swapcase():

​ 将字符串中大写变小写,小写变大写;
str.title():

​ 将字符串中所有单词(通过空格和 ‘ 分割)的首字母大写;

str.capitalize():

​ 仅将字符串的首字母大写;
str.istitle/isupper/islower():

​ 判断字符串是否为对应类型,返回布尔值

2.5调整长度和空白符

str.strip/rstrip/lstrip():

​ 去掉字符串两侧或右侧或左侧的空白字符(空格、制表符、换行符)
str.zfill(int):

​ 在左边填充 0 使其长度变为 width,正负值前缀的处理方式是在正负符号之后填充而非在之前,若指定长度过短则返回原字符串
​ 整数左边去0,直接int()即可

2.6 字符串的表达式求值输出

f”str1{exp}str2”在字符串求值时对exp表达式求值

1
2
3
>>> name = "python"
>>> f"dear {name}"
>>> "dear python"

2.7 字符串的连接

简单的字符串合并可以使用“+”连接,但是字符串为不可变对象因此应该把合并结果赋值给新的字符串。

str.join():

join()方法用于将可迭代对象的元素按照指定的连接符(字符串)连接为新字符串。

本质上相当于被操作字符串填充到可迭代对象的间隙中作为分隔符了。

更重要的应用是把迭代器转为字符串的代码str=””.join(迭代器))【这是将可迭代对象转为不可迭代对象】

1
2
3
4
5
6
>>> x="abc"+"123"
>>> print(x)
>>> "abc123"
>>> x='sep'.join(["1","2","3","4"])
>>> print(x)
>>> "1sep2sep3sep4"

2.8 字符串中的转义字符

转义字符的应用

\t:水平制表符,可以上下对齐(用于制表)
\n:换行符

注:只需要一个换行符的时候,直接输入print()即默认含一个换行符

\x64:字母d的十六进制ascii码,输出时直接变成d,换成\xn则输出以n为ascii码的符号。
在””中如果要表示”,则要写作\”

1
2
3
4
for i in range(1,10):
for j in range(1,i+1):
print('{}x{}={}\t'.format(j,i,i*j),end='')
print()

案例为打印九九乘法表的代码,使用制表符\t便可输出对齐的乘法表,无需计算空格数量。

阻止解释转义字符:在字符串前面加r

1
2
>>> print(r"Hello, \t my friend, \n \t\t Greetings!")
>>> "Hello, \t my friend, \n \t\t Greetings!"

3.元组Tuple ( )

3.1组合与拆分

packing:利用元组将一组数据组合成一个对象 例:atuple = (obj1, obj2)
unpacking:将元组赋值给多个独立变量 例:x, y = atuple,则x = obj1, y = obj2
另例:x, y = input().split(),输入1 2,则x = ‘1’, y = ‘2’

3.2元组性质

可通过下标访问,可切片,可通过tuple()将list,str类型转化为元组
len(atuple)可获取元组元素个数,sorted()由小到大排序, reversed()反转元组(利用tuple()转换为元组)

以上均为元组作为序列的基本性质,不是元组的特殊性质。

元组是不可修改对象,故没有append(),pop(),insert()等方法,只能使用内建函数将结果转移至其他序列。

元组的一个特点是,虽然它本身是不可变对象,但其内部的可变对象仍然可修改。

1
2
3
4
>>> tup=([1,2,3],'123',('1','2','3'))
>>> tup[0][1]=0
>>> print(tup)
>>> ([1, 0, 3], '123', ('1', '2', '3'))

元组最常用的是作为多维数组,形成矩阵:

( (1 , 0) , ( 0 , 1 ) ):一个二维数组,同时可以表示一个二阶矩阵。

4.字典Dict { }

4.1键值对访问

键的内容一般为字符串、整型数字、元组等不可变对象。

值可以重复,但是键不可重复。

adict = {1 : 1, 2 : 4, 3 : 9},则adict[3] = 9,代码直接由键访问值。

4.2创建字典

直接创建: adict = {1 : 1, 2 : 4, 3 : 9}
一个列表(key)创建:令d={},对于key列表中的元素item,直接用赋值法更新其值:d[item]=…
两个列表(key-value)列表创建:bdict = dict(zip(keylist, valuelist)) ,其中两个列表一般等长
一个元素全为二元元组的列表创建:cdict = dict(tuplelist),key为所有元组0号,value为所有元组1号,对应关系不变
字典解析:公式:newdict = {expr : expr for item in iterable if condition == True}
例:adict = {x : x ** 2 for x in range(1, 4) if True},则 adict = {1 : 1, 2 : 4, 3 : 9}
多重对应关系,可以考虑字典套字典

4.3元素修改

直接赋值:adict[3] = 6,则adict = {1:1, 2:4, 3:6}
删除键值对:adict.pop(key),则先返回key对应的值,再删除对应键值对(弹出)

4.4获取元素信息

dict.get(key,default=None)

​ 以直接返回key对应的值。若未查找到则返回default的值。

dict.keys/values()—-注意单词复数形式

​ 返回一个含有所有key/value值的view对象,需用list()等转化为键/值组成的列表。
dict.items()—-注意单词复数形式

​ 返回一个含有所有键值对元组的view对象,需用list()等转化为键值对元组作为元素组成的列表。

4.5 字典的合并更新

dict.update(dict2):

​ 将dict2的键值对更新进dict,如果已经存在对应的键,就更新值。

5.集合Set/Frozenset { }

分为可变集合(set)和不可变集合(frozenset),可迭代。、

集合与数学上的定义一致,有两个显著特征:元素去重,无序

所以和其他序列不同的是,它作为一个无序序列不存在索引、切片

5.1创建集合(自动去重)

例:aset = {1, 1, 2},则aset = {1, 2}、

常用集合作为自动去重工具,例如有一个列表x需要把重复元素删去,则先set(x)再list(x)即可。

5.2集合基本操作

len(set)返回集合元素个数
修改元素:set.add/remove(obj):添加/删除指定元素
set.pop()随机删除一个元素并返回删掉的元素:毕竟是无序序列,没法指定删掉哪个。
set.clear()清空集合
元素判断:in/ not in,返回布尔值
子集判断:aset.issubset(bset)判断aset是否为bset子集;aset.superset(bset)判断aset是否包含bset
集合排序:sorted(aset)返回一个排好序的列表

​ 虽然集合是无序的,但是对它使用sorted()内建函数则会强制排序并变更为有序的列表。

5.3集合运算

适用于可变与不可变集合的常见通用方法为:

交集:aset.intersection(bset, cset, …):

​ 返回一个新的集合对象,即求交集aset&bset&cset…的结果
并集:aset.union(bset, cset, …):

​ 返回一个新的集合对象,即求并集aset|bset|cset….的结果
差集:aset.difference(bset, cset, …):

​ 返回一个新的集合对象,即求差集aset - bset - cset - …的结果
​ aset.symmetric_difference(bset),返回一个新的集合对象,即aset和bset对称差的结果

对于可变集合,则可特殊地写出修改方法:

交集:aset.intersection_update(bset, cset, …)

并集:aset.update(bset, cset, …)

差集:aset.difference_update(bset, cset, …)

6.文件操作

打开文件

有open(”file.txt”)和with open(“file.txt”) as f两种用法,推荐后一种,因为with open() as的打开方式会在结束后自动关闭文件。
打开文件常用模式:(必须作为字符串写入括号参数)

模式 r r+ w w+ a a+
+ + + +
+ + + + +
创建 + + + +
覆盖 + +
指针在开始 + + + +
指针在结尾

例如:

1
2
with open('test.txt','r') as f:
print(f.read())

读取文件内容

f.read()

直接将文本中的全部内容读取进来变成一个换行的字符串,但输出时没有一般字符串类型自带的引号

f.readline()

readline方法从文件中读取整行,包括换行符’\n’
多次使用时,readline记住上一次读取的位置,继续读取下一行

f.readlines()

readlines方法读取所有行,返回的是所有行的字符串组成的列表。

文件改写

f.write()

1
f.write(str) # f为文件对象,str为要写入的字符串

文件关闭

f.close()

常常搭配try:f = open() +finally:f.close()使用,但如果使用with语句可以自动关闭文件无需close()

1
2
3
4
5
6
7
8
9
10
11
try:
f = open('xxx')
data = f.read()
except:
print('fail to open')
finally:
f.close()
-------------------------------------------------------------------------

with open("1.txt") as file:
data = file.read()

练习

1.matrix = [ [1,2,3,4], [5,6,7,8], [9,10,11,12] ]用列表解析一行实现矩阵转置
用zip实现矩阵转置


Author: HuanyuRen
Reprint policy: All articles in this blog are used except for special statements CC BY 4.0 reprint polocy. If reproduced, please indicate source HuanyuRen !
  TOC