数据结构和序列

Python 数据结构简单且强大,常用的数据结构有:元组、列表、字典和集合。


元组是一种固定长度且不可变的 Python 对象序列。

创建元组的方法:最简单的方法是用逗号分割

tup = 1,2,3

python 数据逻辑结构 python构造逻辑数组_数据结构


或者使用 tuple 函数将任意序列或迭代器转换为元组:

tuple([4,5,6]) #将序列转化为元组

python 数据逻辑结构 python构造逻辑数组_Python_02

元组中元素可以通过中括号来获取,事实上,大多数序列类型都可以使用该方法。注意,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. 集合无视顺序。

集合与列表有两点不同:

  1. 集合中元素是独一无二的,正如上述代码nums_set = {3,4,5,1,2,6,7,1}, 当输出nums_set 其中的两个1会被忽略成一个。
  2. 集合中元素的排列顺序无关紧要,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'