数据结构和序列
Python 数据结构简单且强大,常用的数据结构有:元组、列表、字典和集合。
元组是一种固定长度且不可变的 Python 对象序列。
创建元组的方法:最简单的方法是用逗号分割
tup = 1,2,3
或者使用 tuple 函数将任意序列或迭代器转换为元组:
tuple([4,5,6]) #将序列转化为元组
元组中元素可以通过中括号来获取,事实上,大多数序列类型都可以使用该方法。注意,Python 中索引从 0 开始。
tup[2] #结果为 3
注意,元组中各个位置上对象是无法被修改的,例如:tup[0] = 5
会返回 TypeError.
元组中也有一些方法,但由于元组内容、长度无法改变,因此实例方法也很少。
一个常用的方法是 count, 用于计算某个数值在元组中出现的次数。
封包和拆包的一些操作:
# 封包与解包
# 封包:多个值赋给一个变量时,Python 会自动将值封装为元组
# 解包:将序列赋值给多个变量时(len(序列) = len(变量)),各元素依次赋值给每个变量
vals = 10,20
print(type(vals)) # <class 'tuple'>
a, b = vals
print(type(a), type(b)) # <class 'int'> <class 'int'>
# 同时运用封包解包机制
x,y,z = 10,20,30
# 相当于首先 val = 10,20,30 之后 x,y,z = 10,20,30
# 交换变量的值:
x,y,z = z,x,y
# 解包时只分解部分变量,剩下的变量使用列表保存
# 在列表变量前添加一个 '*'
first, second, *rest = range(5)
print(first, second) # 0 1
print(rest) # [2,3,4]
列表是长度、内容可被修改的数据结构。
在 Python 中,使用中括号或 list 函数来定义列表。
a = [1,2,3]
b = list(('test',4, False) #将元组转化为序列
列表与元组除了可被修改/不可修改的区别外,它们很多函数方法是很类似的。
下面给出 list 的一些函数用法:
c = list(range(1,5)) #用range函数生成列表
c.append(6) #在尾部添加元素 6
c.insert(2,7) #在下标2处添加元素 7
c.pop(1) #删除下标1处元素
c.remove(3) #删除指定元素 3
c.extend([8,9]) #连接列表[8,9]内两个元素
c.sort() #排序
Python 中,切片符号恶意对大多数序列类型选取其子集,其基本形式为:[start:end:step]
注意,start 处为闭区间,end 处为开区间。
例如:
seq = [1,2,3,4,5]
seq[1:4:2] #[2,4]
# start, end, step 均可以省略,默认值为起始,结束,步长为1.
# start, end, step 也可以为负值
Python 中有很多有用的序列函数
enumerate 函数:返回(i,value)元组序列, 其中 i 是元素的索引,value 是元素的值:
l = [1,2,3,4,5]
for i, value in enumerate(l):
pass
sorted 函数:返回一个根据任意序列中的元素新建的已排序列表,其接受参数与列表的 sort 方法一致。
sorted('hello world')
#[' ', 'd', 'e', 'h', 'l', 'l', 'l', 'o', 'o', 'r', 'w']
zip 函数:将列表、元组或者其他序列的元素配对,新建一个元组构成的列表:
a = [1,2]
b = ['a','b','c']
list(zip(a,b)) #生成列表长度由最短序列决定
#[(1, 'a'), (2, 'b')]
reversed 函数:将序列的元素反转:
list(reversed([3,2,5,4]))
#[4, 5, 2, 3]
字典,更通俗来说应该称为“哈希表”。
字典是一个键值对集合,{} 是创建字典的一种方式。
# 一个存放成绩的数组
scores = {'language':89, 'math':92, 'physical':93}
print(scores) # {'language': 89, 'math': 92, 'physical': 93}
字典包含多个 key-value 对,key 为关键字,value 为值,类似于数组中 index-value 的对应关系。
需要注意的是,元组可以作为字典的 key, 但是列表不能作为字典的 key. 这反映出字典要求 key 不可变。
字典有很多操作,以示例的形式给出,代码如下:
# 创建字典
# 使用花括号创建
scores = {'language':89, 'math':92, 'physical':93}
# 使用 dict 函数创建
height = dict([('LiHua', 179), ('ZhangSan', 165)])
print(height) #{'LiHua': 179, 'ZhangSan': 165}
# 创建一个空字典
empty_dict1 = {}
empty_dict2 = dict()
# 通过 key 访问 value
print( scores['math']) #92
# 添加一个 key-value 对
scores['chemical'] = 99
print(scores) # {'language': 89, 'math': 92, 'physical': 93, 'chemical': 99}
# 使用 del 删除 key-value 对
del scores['language']
print(scores) # {'math': 92, 'physical': 93, 'chemical': 99}
# 修改一个key-value对, 覆盖 value
scores['math'] = 95
print(scores) # {'math': 95, 'physical': 93, 'chemical': 99}
# 使用 in 判断是否存在指定的 key
print( 'LiHua' in height) # True
print( 'Lihua' not in height) # True
字典也有很多方法,如下:
# clear() 清空字典的所有key-value
height.clear()
print( height == empty_dict1) # True
# get() 依据 key 获取 value
print( scores.get('physical')) #93
# get 与 花括号 不同之处:
# get 访问到不存在的 key 时,返回 None
# 花括号 访问到不存在的 key 时,返回 KeyError
# update() 更新字典:若存在key, 则覆盖 value; 否则创建 key-value
scores.update({'physical': 100, 'English':91})
print(scores) # {'math': 95, 'physical': 100, 'chemical': 99, 'English': 91}
# items() 获取所有key-value
print(scores.items()) # dict_items([('math', 95), ('physical', 100), ('chemical', 99), ('English', 91)])
# keys() 获取所有key
print(scores.keys()) # dict_keys(['math', 'physical', 'chemical', 'English'])
# values() 获取所有value
print(scores.values())#dict_values([95, 100, 99, 91])
# pop() 获取制定key的value, 并删除它
print( scores.pop('chemical')) #99
print(scores) #{'math': 95, 'physical': 100, 'English': 91}
# popitem() 以元组的形式随机弹出字典中的一个 key-value
print( scores.popitem()) #('English', 91)
print(scores) #{'math': 95, 'physical': 100}
# setdefalut 根据key获取value, 当key不存在时,返回一个默认值
print(scores.setdefault('math')) #95
print(scores.setdefault('English',0)) #0, 默认值设置为0
# fromkeys() 使用给定的多个key创建字典,默认的 value 为 None
weight = dict.fromkeys(['LiHua', 'ZhangSan'])
print(weight) #{'LiHua': None, 'ZhangSan': None}
id = dict.fromkeys(['LiHua', 'ZhangSan'], '0000')
print(id) #{'LiHua': '0000', 'ZhangSan': '0000'}
集合,是一种无序且元素唯一的容器。
类似于字典,集合可以看作只有键没有值的字典。
集合的创建方式:
# 使用 set 函数
set([1,2,2,3,3]) #{1,2,3}
# 使用大括号
{1,2,2,3,3} #{1,2,3}
对于集合,有几点说明:1. 集合包含的不是键,而是元素;2. 集合的元素是独一无二的;3. 集合无视顺序。
集合与列表有两点不同:
- 集合中元素是独一无二的,正如上述代码
nums_set = {3,4,5,1,2,6,7,1}
, 当输出nums_set 其中的两个1会被忽略成一个。 - 集合中元素的排列顺序无关紧要,nums_set 输出为
1,2,3,4,5,6,7
.
集合支持大量独特的操作:
nums_set = {3,4,5,1,2,6,7,1}
nums_set.remove(1) # 删除元素1
nums_set.add(8) # 添加元素8
nums_set #{2, 3, 4, 5, 6, 7, 8}
# 两个集合相互操作
nums2 = {1,3,5,7,9}
nums_set - nums2 # 差集
#{8, 2, 4, 6}
nums2 - nums_set # 差集
#{1, 9}
nums2 | nums_set # 并集
#{1, 2, 3, 4, 5, 6, 7, 8, 9}
nums2 ^ nums_set # 对称差
#{1, 2, 4, 6, 8, 9}
nums2 & nums_set # 交集
#{3, 5, 7}
注意,与字典的键一样,集合的元素必须是不可变的。
Python 最受欢迎的语法特性是列表推导式。
基本形式为:[expr for val in collection if condition]
. 与下列 for 循环格式是等价的。
for 表达式的语法格式如下:[表达式 for 循环计数器 in 可迭代对象]
从语法格式中可以看出来,for 表达式与普通 for 循环的区别有两点:1. 在 for 关键字之前定义一个表达式,该表达式通常会包含循环计数器。2. for 表达是没有循环体,因此不需要冒号。
例如:
a_list = [x * x for x in range(10)]
print(a_list) # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
# 添加 if 条件
b_list = [x * x for x in range(10) if x % 2 == 0]
print(b_list) #[0, 4, 16, 36, 64]
# 使用圆括号生成一个generator
c_generator = (x*x for x in range(10) if x % 3 == 0)
# 使用 for 循环迭代生成器
for i in c_generator:
print(i , end = ' ')
# 输出结果为:0 9 36 81
# 嵌套循环
d_list = [(x,y) for x in range(3) for y in range(2)]
print( d_list)
#[(0, 0), (0, 1), (1, 0), (1, 1), (2, 0), (2, 1)]
同样,字典与集合也可以用类似的方式生成。
字典:{key-expr : value-expr for value in collection if condition}
.
集合:{expr for value in collection if condition}
.
函数
函数是 Python 中最重要、最基础的代码组织和代码复用方式。
函数声明时使用 def 关键字,返回时使用 return 关键字,例如:
def sum( a, b, c = 2):
return a + b + c
每个函数都可以有位置参数和关键字参数,关键字参数最常用于指定默认值或可选参数。
在上述例子中, a 与 b 为位置参数,c 为关键字参数。
位置参数与关键字参数的限制在于:关键字参数必须跟在位置参数之后。
Python 不同于 C++/Java, 它的函数可以返回多个值,例如:
def test():
a = 1
b = 2
c = 3
return a,b,c
Python 中函数也是一个对象。
Python 支持 Lambda 函数(匿名函数)。
Lambda 函数是一种通过单个语句生成函数的方式,其结果是返回值。
匿名函数通过 Lambda 关键字定义,该关键字的意思为“声明一个匿名函数”。
例如:
def function( x):
return x*2
f = lambda x:x*2
相比之下,lambda 函数代码量小,且更为清晰。
命名空间
Python 中有两种连接变量的方式:全局、本地。
考虑以下情况:
def test():
a = []
globle b;
b = []
for i in range(5):
a.append(i)
b.append(i)
# a 为临时变量,b 为全局变量
# 执行完 test() 后,a 会被销毁,b 会被保留
错误与异常处理
Python 可以优雅地处理错误/异常。
例如:
#将字符串转化为浮点数
float('1.23') #正确
float('test') #错误,返回ValueError
若我们想要当 float 函数运行失败时可以优雅地返回输入参数,可以通过一个 try/except 代码段实现“
def attemp_float(x):
try:
return float(x)
except:
return x
attemp_float('aa') #会返回 'aa'