[Python learning] 数据结构

这是Python学习的课上笔记,主要内容有数据结构

#Python 简单介绍

作为一种解释型语言,Python 的设计哲学强调代码的可读性和简洁的语法(尤其是使用空格缩进划分代码块,而非使用大括号或者关键词)。

与 Scheme、Ruby、Perl、Tcl 等动态类型编程语言一样,Python 拥有动态类型系统和垃圾回收功能,能够自动管理内存使用,并且支持多种编程范式,包括面向对象、命令式、函数式和过程式编程。其本身拥有一个巨大而广泛的标准库。

Python是完全物件导向的语言。函数、模组、数字、字串都是物件。并且完全支持继承、重载、派生、多重继承,有益于增强原始码的复用性。Python 支持重载运算符,因此 Python 也支持泛型设计。

Python 编译器本身也可以被集成到其它需要脚本语言的程式内。因此,有很多人把 Python 作为一种*“胶水语言”*使用。使用 Python 将其他语言编写的程式进行集成和封装。

Python 属于动态类型语言,动态类型语言是在运行期间检查数据的类型,不得不保持描述变量值的实际类型标记,程序在每次操作变量时,需要执行数据依赖分支,而静态类型语言相对于动态类型语言,在声明变量时已经指定了数据类型和表示方法,根据这一原理导致 Python 相对于 C、Visual Basic 等静态类型语言来说运行速度较慢

摘录自 Wikipedia

#Python 数据类型

#常量

Python 中没有关键字表示常量,用大写来代表这是一个常量。例如 NUM=5NUM 就是一个常量。因此,在编写 Python 代码时,要严格区分大小写。

#变量

Python 中变量声明不需要声明变量类型。

但是,Python 是一种强类型语言,不能因此而判断 Python 是弱类型的。

Python 是动态的、强类型的语言。

Why is Python a dynamic language and also a strongly typed language?

#数据类型

#分为两大类:内置数据类型、自定义数据类型

内置数据类型分为:数值、序列、集合、字典、特殊、其他

数值数据类型:整数、浮点数、布尔、复数

序列数据类型:字符串、元组、字节序列、列表、字节数组

集合数据类型:集、不可变集

#内置的 type() 函数可以用来查询变量所指的对象类型

1
2
3
 >>> a, b, c, d = 20, 5.5, True, 4+3j
 >>> print(type(a), type(b), type(c), type(d))
 <type 'int'> <type 'float'> <type 'bool'> <type 'complex'>

#int 类型

1
2
3
4
5
myInt = 5 
myInt = int(5) #int对象方式
int(5.4) #自动类型转换
int("123") #自动类型转换
#二进制以0b开头,八进制以0开头,十六进制以0x开头

#float 类型

1
2
myFloat = float(3.14)
myFloat = float(4) #自动类型转换,输出结果4.0

#复数数据类型 虚部必须用 j

1
2
3
4
5
6
1+1j #不可写成1+j
0+0j #0不能省略
complex(1,2) #其中1为实部,2为虚部
c1=complex(6) #输出c1为6+0j,等同于complex(6,0) complex(6,)
c2=complex(2.1,3.2) #实部与虚部可以为浮点数
#real:复数的实部 imag:复数的虚部  c2.real输出结果2.1,c2.imag输出结果3.2

#bool 类型

1
2
3
4
5
"""
True False开头首字母必须大写
bool对象 bool(False)
bool(0),bool(0.0) 结果为False,任何非零均为True例如   bool('0'),bool(5),bool(2.3),bool("abc")
"""

#String类型

#表现形式

"abc"'abc''''abc'''"""abc""", 前两个表示一行,后两个表示可以跨行。

#字符串拼接与重复
1
2
3
4
5
6
>>> "abc"+'def'  #使用+进行字符串连接
'abcdef'
>>> "abc" 'def'  #默认自动连接
'abcdef'
>>> "abc"*2  # *表示重复,*后的整数表示重复次数
'abcabc'
#转义字符
转义字符 含义
\n 换行
\r 回车
\t 水平制表符
\v 垂直制表符
\b 退格
\f 换页

使用 rR 为开头的字符串成为原始字符串,其中包含的任何字符都不可进行转义。

1
2
3
>>> myStr = r"abc\n"
>>> print(myStr)
'abc\n'
#str 对象

str()

str(.14) 输出结果为 '0.14' ,浮点数前导 0 可省略,隐式类型转换。

#字符串索引

Python 中的字符串有两种索引方式,第一种是从左往右,从 0 开始依次增加;第二种是从右往左,从 -1 开始依次减少。

注意,没有单独的字符类型,一个字符就是长度为 1 的字符串。

1
2
3
4
5
>>> word = 'Python'
>>> print(word[0], word[5])
P n
>>> print(word[-1], word[-6])
n P
#字符串截取子串

用冒号分隔两个索引,形式为变量[头下标:尾下标]。

截取的范围是前闭后开的,并且两个索引都可以省略:

1
2
3
4
5
6
7
8
9
>>> word = 'ilovePython'
>>> word[1:5]
'love'
>>> word[:]
'ilovePython'
>>> word[5:]
'Python'
>>> word[-10:-6]
'love'

Python 字符串不能被改变。向一个索引位置赋值,比如 word[0] = 'm' 会导致错误。

#列表

#列表的创建方式
#字面量

[x1,x2,x3,x4,...,xn]

列表中元素类型可以不同,如 [1, 2, 3, 'q', True]

列表中的元素可以是表达式,如

1
2
3
x = 1
temp = [x + x, x * x, 11]
list = [[1,2,3,4],[5,6,7],8]
#对象
1
2
3
list1 = list()  #空列表
list2 = list("abcd")  #结果['a', 'b', 'c', 'd']
list3 = list(range(3))  #结果[0, 1, 2]
#推导式

使用非常简单的表达式满足特定的列表

表达式 for 变量 in 序列

1
2
3
list4 = [x*x for x in range(1,10)]
print(list4)   #结果[1, 4, 9, 16, 25, 36, 49, 64, 81]
list5 = [i for i in list4 if i%2==0]  #结果[4, 16, 36, 64]
#列表的操作

列表的操作包括:索引、切片、连接、重复、成员关系、比较、求长度、最大值、最小值等

#索引访问
1
2
3
list6 = [1, 2, 3]
print(list6[0], list6[-1])  #结果1 3
list6[0] = 10  #list中的值可以改变,此时list6为[10, 2, 3]
#删除列表中的元素
1
2
list7 = [1,2,3,4,5]  #[1,2,3,4,5]
del list7[1]  #[1,3,4,5]
#求长度、最大值、最小值、和
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
list8 = [1,2,3,4,5,6]  #[1,2,3,4,5,6]
len(list8)  #6
min(list8)  #1
max(list8)  #6
sum(list8)  #21
list9 = [1,2,3,4,'a',5]
len(list9)  #6
max(list9)  #TypeError: unorderable types: str() > int(), min和sum同样错误。
list10 = ['a', 'b', 'c']  #可以算len,max,min,但不能求和

# Python 2.7.15中测试结果如下
>>> list1 = [1,2,3,4,5,'a', 6]
>>> max(list1)
'a'
>>> min(list1)
1
>>> sum(list1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'int' and 'str'
#切片

s[i:j]:从索引 i 开始,到j结束,左闭右开。省略 i 从 0 开始,省略 j 到结尾结束

s[i:j:k]:k 表示步长

1
2
3
4
list1 = [1, 2, 3, 4, 5, 6, 7]
temp = list1[1:6:2]
print(temp)  # 结果[2, 4, 6]
list1[:1] = []  # list1变为[2,3,4,5,6,7]
#连接与重复

连接 +,重复 *

1
2
3
4
5
list2 = [1,2,3]
list3 = [3,4,5]
print(list2+list3)  # 结果[1, 2, 3, 3, 4, 5],只连接不去重
print(2*list2)  # 结果[1, 2, 3, 1, 2, 3]
list2 += list3  # 结果[1, 2, 3, 3, 4, 5],等价于list2 = list2 + list3
#成员关系操作

判断一个元素是否在列表中:innot in

1
2
3
4
5
list1 = [1, 4, 3, 3, 2, 2, 3]
print(7 in list1)  # False
print(3 in list1)  # True
print(list1.count(3))  # 3  计算某一个元素在列表中出现的次数
print(list1.index(3, 2, 6))  # 2 查找某个元素在给定范围内第一次出现的索引,例子中范围为[2,6)
#比较运算
1
2
3
4
5
6
7
8
list1 = ['a', 'b']
list2 = ['a', 'b']
list3 = ['a', 'b', 'c']
list4 = ['c', 'b', 'a']
print(list1 == list2)  # True
print(list3 > list2)   # True
print(list3 > list4)   # False
# 从第一个元素开始比较
#列表的排序

sorted(list1))

#any()和all()

any():列表中是否有元素为 True

all():列表中的元素是否都为 True

#列表的拆分
1
2
3
4
list1 = [1,2,3,4]
a,b,c,d = list1
print(a,b,c,d)  # 结果1 2 3 4
# 应保证前面的变量数与列表的长度相同

#元组

#定义与声明

定值表,用来存储不变值表

1
2
3
4
5
6
7
8
9
t = 1,2,3,4         # 表示元组
t = (1,2,3,4)       # 表示元组
t = ()              # 表示空元组
t = 1,              # 表示只有一个元素的元组,必须有逗号
t = tuple(1,2,3,4)  # 错误写法,只能有一个参数
t = tuple([1,2,3,4])# 正确写法
t = tuple("abcd")   # 结果为('a','b','c','d')
t = tuple(range(8)) 
t = tuple(2*x for x in range(1,5)) # 结果为(2,4,6,8)
#元组的操作

索引访问、切片、连接、重复、成员关系、最大值、最小值、和、长度、排序等,与列表的操作类似,可以进行对比。一些内容不作赘述。

#元组的排序
1
2
3
4
5
6
7
8
9
tuple1 = tuple([2,1,9,5,4,6])
print(tuple1)
print(sorted(tuple1))
print(tuple1)

# 结果为
(2, 1, 9, 5, 4, 6)
[1, 2, 4, 5, 6, 9]  # 输出的是列表
(2, 1, 9, 5, 4, 6)  # 原元组没有变化
#元组的拆分
1
2
3
4
5
6
7
8
9
a, *s, d, f = tuple1 
print(a, d, f)      # 结果为 2 4 6
a, s, d, *f = tuple1
print(a, s, d)      # 结果为 2 1 9
# 元组的拆分前面变量的个数必须与元组元素个数相等。如果元组元素个数过多,可以使用*代表多个变量

_, a, b, _, *_ = tuple1
print(a, b, _)      # 结果为 1 9 [4, 6]
# 没有意义的命名可以使用临时变量下划线(_)表示。输出临时变量,只会保留最后一个。

#字典

#字面量

{键:值,键:值,键:值,键:值,}

#字典对象

dict()

1
2
3
4
5
print(dict([['优',90],['良',80]]))
print(dict((('优',90),('良',80))))
print(dict(zip(['优','良'],[90,80])))
# 结果均为 {'优': 90, '良': 80}
dict1 = dict(a="apple", b="banane")  # {'a':'apple', 'b':'banane'}
#fromkeys()
1
2
3
dict2 = {}.fromkeys(['优','良'],"大于70分")  # {'优': '大于70分', '良': '大于70分'}
dict3 = {}.fromkeys(['优','良'])  # {'优': None, '良': None}
dict4 = {}.fromkeys(['优','良'],None)  # {'优': None, '良': None}
#推导式
1
dict5 = {n:n**2 for n in range(1,5)} # {1:1,2:4,3:9,4:16}
#得到键对应的值
1
2
3
4
5
6
7
8
dict2['优']  # 大于70分
dict2.get('优')  # 大于70分
dict2.get('秀')  # 没有反应,也没有报错
dict2.get('秀','自定义错误提示')  # 如果有“秀”对应的值,则输出对应的值;否则输出后面的提示信息
dict2.get('优', '自定义错误提示')  # 大于70分
dict2.items()  # 获取所有的键值对
dict2.keys()  # 返回所有的键值
dict2.values()  #返回所有的值
#添加键值对
1
2
dict1['c'] = cat  # {'a':'apple', 'b':'banane', 'c':'cat'} 没有则添加
dict1['a'] = allen  # {'a':'allen', 'b':'banane'} 有则修改
#合并
1
2
3
4
5
dict6 = {'No1':'java','No2':'Python'}
dict7 = {'No3':'C++'}
dict8 = {'No2','C'}
dict6.update(dict7)  # dict6为{'No1': 'java', 'No2': 'Python', 'No3': 'C++'}
dict6.update(dict8)  # dict6为{'No1':'java','No2':'C', 'No3': 'C++'}
#删除
1
2
3
4
5
6
7
8
9
del(dict6['No2'])
print(dict6)  # {'No1': 'java', 'No3': 'C++'}
del dict6
print(dict6)  # 报错,未定义dict1

dict6.pop('No2','自定义错误提示')  # 存在则删除;不存在输出自定义错误提示,即参数二
dict9 = {'No1':'java','No2':'Python','No3':'C++'}
dict9.popitem()  # 从后往前删除,每次删除一个。先删除No3,再删除No2...
dict9.clear()  # dict9为 {}

#集合

可变集合(set) 不可变集合(frozenset),没有顺序,没有重复元素。

#字面量
1
2
3
4
print({1,2,3,4})  # {1, 2, 3, 4}
print({1,2,1,4})  # {1, 2, 4}
print({1,True})   # {1}
print({1,False})  # {False, 1}
#对象
1
2
3
4
set1 = set('hello')    # {'h', 'e', 'l', 'o'}
set2 = set((1,2,3,4))  # {1, 2, 3, 4}
set3 = set([1,2,3,4])  # {1, 2, 3, 4}
set4 = set((1,[2,3,4]))# 错误
#推导式
1
{x*x for x in range(1,5)}  # {16, 1, 4, 9}
#交并差集
1
2
3
4
5
6
set5 = set(1,2,3,4)
set6 = set(3,4,5,6)
set5 | set6  # 并集 {1, 2, 3, 4, 5, 6} 
set5 & set6  # 交集 {3, 4} 
set5 - set6  # 差集 {1, 2} 
set5 ^ set6  # 对称差集 {1, 2, 5, 6}
#合并
1
set5.update(set6)  # {1,2,3,4,5,6}
#拷贝
1
set7 = set6.copy()
updatedupdated2022-05-032022-05-03