【Python】-2.Python中数据结构


1. 序列的通用操作

Python中有六种内置序列(列表、元组、字符串、Unicode字符串、buffer对象和 xrange 对象),可以对它们进行一些通用的操作。其中有三种序列比较常见:列表、元组、字符串。

通用序列操作:索引、切片、序列相加、乘法、成员资格、长度、最小值和最大值

1.1 索引

1.1.1 从左往右检索

# 列表
x1 = [1, 2, 3, 4]
print(x1[0]) # 1
print(x1[1]) # 2

# 元组
x2 = (1, 2, 3, 4)
print(x2[0]) # 1
print(x2[1]) # 2

1.1.2 从右往左编号检索

# 列表
x1 = [1, 2, 3, 4]
print(x1[-1]) # 4
print(x1[-2]) # 3

# 元组
x2 = (1, 2, 3, 4)
print(x2[-1]) # 4
print(x2[-2]) # 3

1.2 切片

1.2.1 从左往右切片

# 列表
x1 = [1, 2, 3, 4]
print(x1[0:3]) # [1, 2, 3]
print(x1[2:3]) # [3]

# 元组
x2 = (1, 2, 3, 4)
print(x2[0:3]) # (1, 2, 3)
print(x2[2:3]) # (3,)

# 字符串
x3 = "1234"
print(x3[0:3]) # 123
print(x3[2:3]) # 3

1.2.2 从右往左进行切片

# 列表
x1 = [1, 2, 3, 4]
print(x1[-3:3]) # [2, 3]

# 元组
x2 = (1, 2, 3, 4)
print(x2[-3:3]) # (2, 3)

# 字符串
x3 = "1234"
print(x3[-3:3]) # 23

切片原理

#  +---+---+---+---+
#  | 1 | 2 | 3 | 4 |
#  +---+---+---+---+
#    0   1   2   3
#   -4  -3  -2  -1

1.2.3 切片索引越界

切片时,索引下标超出真实长度

# 列表
x1 = [1, 2, 3, 4]
print(x1[3:10]) # [4]

# 元组
x2 = (1, 2, 3, 4)
print(x2[3:10]) # (4,)

# 字符串
x3 = "1234"
print(x3[3:10]) # 4

1.2.4 切片索引选填

切片时,两个索引参数选填

# 列表
x1 = [1, 2, 3, 4]
print(x1[3:]) # [4]
print(x1[:3]) # [1, 2, 3]
print(x1[:]) # [1, 2, 3, 4]

# 元组
x2 = (1, 2, 3, 4)
print(x2[3:]) # (4,)
print(x2[:3]) # (1, 2, 3)
print(x2[:]) # (1, 2, 3, 4)

# 字符串
x3 = "1234"
print(x3[3:]) # 4
print(x3[:3]) # 123
print(x3[:]) # 1234

1.2.5 切片后的不连续序列

在进行切片时,我们可以根据需求提供起始位置和结束位置来获取任意序列,不过这种方式获取到的序列是连续的。

# 如果要获取不连续的序列,需要用到第三个参数:步长。步长默认情况下为 “1”
# 列表
x1 = [1, 2, 3, 4, 5, 6, 7]
print(x1[1:5]) # [2, 3, 4, 5]
print(x1[1:5:1]) # [2, 3, 4, 5]

# 元组
x2 = (1, 2, 3, 4, 5, 6, 7)
print(x2[1:5]) # (2, 3, 4, 5)
print(x2[1:5:1]) # (2, 3, 4, 5)

# 字符串
x3 = "1234567"
print(x3[1:5]) # 2345
print(x3[1:5:1]) # 2345

1.2.6 切片的步长大于1

切片的步长设置为 2、3

# 列表
x1 = [1, 2, 3, 4, 5, 6, 7]
# 第二个参数为空,表示取到序列的末尾
print(x1[1::2]) # [2, 4, 6]
print(x1[1::3]) # [2, 5]

# 元组
x2 = (1, 2, 3, 4, 5, 6, 7)
print(x2[1::2]) # (2, 4, 6)
print(x2[1::3]) # (2, 5)

# 字符串
x3 = "1234567"
print(x3[1::2]) # 246
print(x3[1::3]) # 25

1.2.7 切片的步长为 0

步长不能为 0,否则出现 “ValueError: slice step cannot be zero” 错误

# 列表
x1 = [1, 2, 3, 4, 5, 6, 7]
print(x1[1::0]) # ValueError: slice step cannot be zero

# 元组
x2 = (1, 2, 3, 4, 5, 6, 7)
print(x2[1::0]) # ValueError: slice step cannot be zero

# 字符串
x3 = "1234567"
print(x3[1::0]) # ValueError: slice step cannot be zero

1.2.8 切片的步长为负数

当负数作为步长时,Python 会从序列的尾部开始向左取元素,直到第一个元素为止。正数的步长则是从序列的头部开始从左往右获取元素,负数正好相反。

所以正数的步长开始点必须小于结束点,负数的步长开始点必须大于结束点

# 列表
x1 = [1, 2, 3, 4, 5, 6, 7]
print(x1[5::-1]) # [6, 5, 4, 3, 2, 1]
print(x1[5::-2]) # [6, 4, 2]

# 元组
x2 = (1, 2, 3, 4, 5, 6, 7)
print(x2[5::-1]) # (6, 5, 4, 3, 2, 1)
print(x2[5::-2]) # (6, 4, 2)

# 字符串
x3 = "1234567"
print(x3[5::-1]) # 654321
print(x3[5::-2]) # 642

1.3 序列相加

1.3.1 相同类型序列相加

序列之间可以使用 “+”(加号) 进行连接操作

# 列表
x1 = [1, 2, 3] + [4, 5, 6, 7]
print(x1) # [1, 2, 3, 4, 5, 6, 7]

# 元组
x2 = (1, 2, 3) + (4, 5, 6, 7)
print(x2) # (1, 2, 3, 4, 5, 6, 7)

# 字符串
x3 = "123" + "4567"
print(x3) # 1234567

1.3.2 不同类型序列相加

序列和序列之间通过加号进行连接,连接后的结果还是相同类型的序列。但是不同类型的序列不能相互连接

# 不同类型不能相加: 
x1 = [1, 2, 3] + (4, 5, 6, 7) # TypeError: can only concatenate list (not "tuple") to list
x2 = "123" + [4, 5, 6, 7] # # TypeError: can only concatenate str (not "list") to str

1.4 序列重复

*使用 * 对序列做 “乘法” 操作*

# 列表
x1 = [1, 2, 3] * 5
print(x1) # [1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3]

# 元组
x2 = (1, 2, 3) * 5
print(x2) # (1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3)

# 字符串
x3 = "123" * 5
print(x3) # 123123123123123

1.5 成员资格

判断一个元素是否包含在序列中,Python 中使用 “in” 来判断。“in” 运算符会判断左边的元素是否包含在右边的序列中,如果包含返回 True,否则返回 False

# 列表
print(5 in [1, 2, 3, 4, 5, 6, 7]) # True
print("Hi" in [1, 2, 3, 4, 5, 6, 7]) # False

# 元组
print(5 in (1, 2, 3, 4, 5, 6, 7)) # True
print("Hi" in (1, 2, 3, 4, 5, 6, 7)) # False

# 字符串
# 注意这里的 5 是字符串类型,上面都是数字类型
print("5" in "1234567") # True
print("Hi" in "1234567") # False

注意:只有当元素的类型和序列的类型完全一致时,才算包含在序列中。如果是两个不同的类型,会出现错误

# TypeError: 'in <string>' requires string as left operand, not int
print(5 in "1234567") 

1.6 长度、最大值、最小值、求和

# 列表
x1 = [1, 2, 3, 4, 5, 6, 7]
print("列表的长度:", len(x1)) # 列表的长度: 7
print("列表的最小值:", min(x1)) # 列表的最小值: 1
print("列表的最大值:", max(x1)) # 列表的最大值: 7
print("列表求和:", sum(x1)) # 列表求和: 28

# 元组
x2 = (1, 2, 3, 4, 5, 6, 7)
print("元组的长度:", len(x2)) # 元组的长度: 7
print("元组的最小值:", min(x2)) # 元组的最小值: 1
print("元组的最大值:", max(x2)) # 元组的最大值: 7
print("元组求和:", sum(x2)) # 元组求和: 28

# 字符串
x3 = "1234567"
print("字符串的长度:", len(x3)) # 字符串的长度: 7
print("字符串的最小值:", min(x3)) # 字符串的最小值: 1
print("字符串的最大值:", max(x3)) # 字符串的最大值: 7

2. 列表

2.1 列表更新

2.1.1 通过索引更新

列表可以通过索引获取其中的单个元素,也可以通过索引更新其中的元素,使用方法和变量赋值一样

l1 = [1, 2, 3, 4, 5]
print(l1[2]) # 3
l1[2] = 'Hello'
print(l1) # [1, 2, 'Hello', 4, 5]

2.1.2 更新索引越界

列表可以存储不同类型的数据,修改的新元素也不需要和原来的元素类型一致。但是要注意,更新列表的索引必须是已存在的索引,不能超出列表的长度

l1 = [1, 2, 3, 4, 5]
# 出现错误: IndexError: list assignment index out of range
l1[10] = "Hello"

2.2 增加元素

2.2.1 追加单个元素

列表不能通过索引来增加元素,索引只能更新现有的元素。如果想要添加新元素,可以使用 append 方法在列表的末尾追加元素

l1 = [1, 2, 3, 4, 5]
l1.append("Hello")
print(l1) # [1, 2, 3, 4, 5, 'Hello']

2.2.2 追加多个元素

append 每次只能新增一个元素,如果想新增多个元素要使用 extend 方法

l1 = [1, 2, 3, 4, 5]
l2 = [1, 2, 3, 4, 5]
l1.append([6, 7])
l2.extend([6, 7])
print(l1) # [1, 2, 3, 4, 5, [6, 7]]
print(l2) # [1, 2, 3, 4, 5, 6, 7]

2.2.3 插入元素

append 和 extend 都是在列表的最后追加元素,如果要在中间插入元素,使用 insert 方法

l1 = [1, 2, 3, 4, 5]
print(l1) # [1, 2, 3, 4, 5]
l1.insert(2, "Hello")
print(l1) # [1, 2, 'Hello', 3, 4, 5]

2.3 删除元素

2.3.1 根据位置删除

pop 函数可以删除列表中指定位置的元素,并且把这个元素作为返回值返回,如果不指定位置则默认选择最后一个元素。

l1 = [1, 2, 3, 4, 5]
print(l1.pop()) # 5
print(l1) # [1, 2, 3, 4]

l2 = [1, 2, 3, 4, 5]
print(l2.pop(2)) # 3
print(l2) # [1, 2, 4, 5]
print(type(l2)) # <class 'list'>

2.3.2 根据内容删除

remove 不但可以根据位置来删除元素,还可以根据元素内容来进行删除。remove 删除查找到的一个元素,没有返回值

l1 = ["Hello", "Google", "Baidu", "QQ"]
print(l1) # ['Hello', 'Google', 'Baidu', 'QQ']
l1.remove("Baidu")
print(l1) # ['Hello', 'Google', 'QQ']

2.3.3 使用关键字删除

不但可以用列表自带的方法对列表元素进行删除,也可以使用关键字 “del” 来删除列表元素

l1 = ["Hello", "Google", "Baidu", "QQ"]
print(l1) # ['Hello', 'Google', 'Baidu', 'QQ']
del l1[2]
print(l1) # ['Hello', 'Google', 'QQ']

2.4 查找元素

Python 中提供了 index 方法用于查找元素在列表中的索引位置

l1 = ["Hello", "Google", "Baidu", "QQ"]
print("Baidu index is: ", l1.index("Baidu")) # Baidu index is:  2
print("QQ index is: ", l1.index("QQ")) # QQ index is:  3

要注意,如果元素不在列表中,Python 解释器会输出错误信息

l1 = ["Hello", "Google", "Baidu", "QQ"]
# ValueError: 'Taobao' is not in list
print("Taobao index is: ", l1.index("Taobao"))

2.5 其他操作

2.5.1 反转

reverse 方法可以反转队列,和 “[::-1]” 类似,但是 reverse 方法修改的是原来的队列,并且没有返回值

l1 = [1, 2, 3, 4, 5]
print(l1) # [1, 2, 3, 4, 5]
l1.reverse()
print(l1) # [5, 4, 3, 2, 1]

2.5.2 计数

count 方法用于统计某个元素在列表中出现的次数

l1 = ["Hello", "Google", "Baidu", "QQ", "01", "Hello"]
print(l1) # ['Hello', 'Google', 'Baidu', 'QQ', '01', 'Hello']
print(l1.count("Hello")) # 2
print(l1.count("Taobao")) # 0

2.5.3 排序

sort 方法用于对列表进行排序,还可以自定义排序方式。sort 会修改原有列表的排序,没有返回值

l1 = [1, 100, 74, 16, 3]
print(l1) # [1, 100, 74, 16, 3]
l1.sort()
print(l1) # [1, 3, 16, 74, 100]

3. 元组

元组与列表十分相似,大部分方法都通用,但是元组与列表最大的区别是:列表可以修改、读取、删除元素,而元组创建之后不能修改,不能删除单个元素,但是可以删除整个元组

3.1 定义元组

元组定义和列表类似,定义元组时只需要用 “(” 和 “)” 把元素括起来,并且用 “,” 把元素隔开就可以了

l1 = (1, 2, 3)
print(l1) # (1, 2, 3)
print(type(l1)) # <class 'tuple'>

注意: 如果元组只有一个元素,则这个元素后面必须要有 “,”,否则元素就还是器原来的类型

l1 = (1)
print(l1, type(l1)) # 1 <class 'int'>
l2 = (1,)
print(l1, type(l2)) # 1 <class 'tuple'>
l3 = ("Hello")
print(l3, type(l3)) # Hello <class 'str'>
l4 = ("Hello",)
print(l4, type(l4)) # ('Hello',) <class 'tuple'>

3.2 删除元组

由于元组不能修改,所以元组不能单独删除部分元素,要删除只能删除整个元组。

l1 = (1,2,3,4)
del l1
# 已删除,无法输出: NameError: name 'l1' is not defined
print(l1)

3.3 其他操作

3.3.1 计数

count 方法用于统计某个元素在元组中出现的次数

l1 = ("Hello", "Google", "Baidu", "QQ", "01", "Hello")
print(l1) # ('Hello', 'Google', 'Baidu', 'QQ', '01', 'Hello')
print(l1.count("Hello")) # 2
print(l1.count("Taobao")) # 0

3.3.2 查找

index 方法用于查找元组中元素的位置

l1 = ("Hello", "Google", "Baidu", "QQ")
print("Baidu index is: ", l1.index("Baidu")) # Baidu index is:  2
print("QQ index is: ", l1.index("QQ")) # QQ index is:  3

4. 字典

字典(dict)类型就和它的名字一样,可以像查字典一样去查找。其他语言也有类似的类型,如PHP中Array,Java中HashMap。

4.1 定义字典

english = {
    "we": "我们",
    "world": "世界",
    "company": "公司"
}
# {'we': '我们', 'world': '世界', 'company': '公司'} <class 'dict'>
print(english, type(english))

字典中元素都是成对出现,每个元素都由键值构成,元素之间用 “,” 分隔。字典中 键 必须是唯一的,空字典直接用 “{}” 表示

empty = {}
print(empty, type(empty)) # {} <class 'dict'>

4.2 使用字典

4.2.1 访问元素

english = {
    "we": "我们",
    "world": "世界",
    "company": "公司"
}
print("world", english["world"]) # world 世界

注意:上面这种方式只能获取已存在的键值对,如果尝试访问不存在的键,Python 将会显示错误信息。

# 访问不存在的键 city: KeyError: 'city'
print("city", english["city"])

4.2.2 修改元素

字典修改元素: 字典和列表一样,都是可修改的结构。修改的方式类似

english = {
    "we": "我们",
    "world": "城市",
    "company": "公司"
}
print(english) # {'we': '我们', 'world': '城市', 'company': '公司'}
english["world"] = "世界"
print(english) # {'we': '我们', 'world': '世界', 'company': '公司'}

4.2.3 新增元素

字典新增元素: 字典新增元素和修改元素的方法是一样的

english = {}
print(english) # {}
english["city"] = "城市"
print(english) # {'city': '城市'}

4.2.4 删除元素

字典删除元素: 字典和列表一样,都是可修改的结构。所以字典中元素也可以被删除

english = {
    "we": "我们",
    "world": "世界",
    "company": "公司"
}
print(english) # {'we': '我们', 'world': '世界', 'company': '公司'}
del english["world"]
print(english) # {'we': '我们', 'company': '公司'}

4.3 其他操作

4.3.1 清空字典

clear 方法可以用于清空字典,使字典变成空字典

english = {
    "we": "我们",
    "world": "世界",
    "company": "公司"
}
print(english) # {'we': '我们', 'world': '世界', 'company': '公司'}
english.clear()
print(english) # {}

4.3.2 拷贝字典

copy 方法可以返回一个拥有相同键值对的新字典。

字典和列表一样,如果只是赋值的话只是引用了之前的内容,如果做修改就会改变原先的字典。copy 方法类似于列表的 “[:]”语法,相当于完整地复制了一份新的副本

english1 = {
    "we": "我们",
    "world": "世界",
    "company": "公司"
}
english2 = english1
english3 = english1.copy()
print("english1", english1) # english1 {'we': '我们', 'world': '世界', 'company': '公司'}
print("english2", english2) # english2 {'we': '我们', 'world': '世界', 'company': '公司'}
print("english3", english3) # english3 {'we': '我们', 'world': '世界', 'company': '公司'}
print("------------------------------- dict changed 1 -------------------------------")
english2["city"] = "城市"
print("english1", english1) # english1 {'we': '我们', 'world': '世界', 'company': '公司', 'city': '城市'}
print("english2", english2) # english2 {'we': '我们', 'world': '世界', 'company': '公司', 'city': '城市'}
print("english3", english3) # english3 {'we': '我们', 'world': '世界', 'company': '公司'}
print("------------------------------- dict changed 2 -------------------------------")
english3["school"] = "学校"
print("english1", english1) # english1 {'we': '我们', 'world': '世界', 'company': '公司', 'city': '城市'}
print("english2", english2) # english2 {'we': '我们', 'world': '世界', 'company': '公司', 'city': '城市'}
print("english3", english3) # english3 {'we': '我们', 'world': '世界', 'company': '公司', 'school': '学校'}

4.3.3 使用键创建新字典

fromkeys 方法用于创建一个新的字典,用序列号中的元素作为字典的键,第二个参数为字典中所有参数对应的初始值

seq = ("name", "age", "class")
student1 = dict.fromkeys(seq)
print("不指定初始值:", student1) # 不指定初始值: {'name': None, 'age': None, 'class': None}
student2 = dict.fromkeys(seq, 15)
print("指定初始值:", student2) # 指定初始值: {'name': 15, 'age': 15, 'class': 15}

4.3.4 获取指定键的值

get 方法可以返回键对应的值,如果字典不存在对应的键则返回默认值

english = {
    "we": "我们",
    "world": "世界",
    "company": "公司"
}
print("world: ", english.get("world")) # world:  世界
print("city: ", english.get("city")) # city:  None
print("city: ", english.get("city", "未知")) # city:  未知

4.3.5 获取所有键

keys 方法返回一个列表,里面包含了字典的所有键

english = {
    "we": "我们",
    "world": "世界",
    "company": "公司"
}
print(english.keys()) # dict_keys(['we', 'world', 'company'])

# keys 方法常用语判断一个键是否存在于列表中,可以与 “in” 组合使用
print("是否存在 world:", "world" in english.keys()) # 是否存在 world: True
print("是否存在 city:", "city" in english.keys()) # 是否存在 city: False

4.3.6 获取所有值

values 方法返回一个列表,里面包含了字典的所有值

english = {
    "we": "我们",
    "world": "世界",
    "company": "公司"
}
print("english 中的值:", english.values()) # english 中的值: dict_values(['我们', '世界', '公司'])

4.3.7 获取所有键值

items 方法返回一个列表,里面包含了键的列表和所有值的列表

english = {
    "we": "我们",
    "world": "世界",
    "company": "公司"
}
print(english.items()) # dict_items([('we', '我们'), ('world', '世界'), ('company', '公司')])

# 由于字典不能直接应用于 for 循环中,可以使用 items 类遍历字典
for k, v in english.items():
    print(k, "=>", v)

# we => 我们
# world => 世界
# company => 公司

5. 集合

Python 中有一种内置类型叫做集合(Set),它与列表类似,唯一区别在于集合不包含重复的值

5.1 定义集合

empty = set()  # 注意空集合不能使用 {} 定义
print("空集合", empty) # 空集合 set()
number = {1, 2, 3}
print("数字集合", number) # 数字集合 {1, 2, 3}
mix = set([1, "您好", 3.14])
print("混合类型的集合", mix) # 混合类型的集合 {3.14, 1, '您好'}

5.2 添加元素

number = {1, 2, 3}
print(number) # {1, 2, 3}
number.add(5)
print(number) # {1, 2, 3, 5}

# 不能存放重复的元素
number.add(2)
print(number) # {1, 2, 3, 5}

5.3 删除元素

number = {1, 2, 3, 4, 5}
print(number) # {1, 2, 3, 4, 5}
number.remove(3) 
print(number) # {1, 2, 4, 5}
number.remove(5) 
print(number) # {1, 2, 4}

如果删除不存在的元素,将会报错

number.remove(6) # KeyError: 6

5.4 集合操作

集合操作(交集、并集、差集、对称差集)

n1 = {1, 3, 5}
n2 = {2, 7, 1, 3}
print("n1", n1) # n1 {1, 3, 5}
print("n2", n2) # n2 {1, 2, 3, 7}
print("交集", n1 & n2) # 交集 {1, 3}
print("并集", n1 | n2) # 并集 {1, 2, 3, 5, 7}
print("差集", n1 - n2) # 差集 {5}
print("对称差集", n1 ^ n2) # 对称差集 {2, 5, 7}

6. 推导式

Python 支持三种推导式(或者称为解析式),分别对应 列表、字典和集合。它能够以非常自然、简单的方式构建列表、字典和集合

6.1 列表推导式

列表推导式的语法: 用中括号括起来,中间使用for预计,后面跟着if语句作判断,满足条件的传到for语句前面用作构建的列表。

l1 = [x for x in range(5)]
print(l1) # [0, 1, 2, 3, 4]

odd = [x for x in range(10) if x % 2 != 0]
print(odd) # [1, 3, 5, 7, 9]

列表推导式可以用于对整个列表做相同的操作,然后得到一个新列表

6.2 字典推导式

字典推导式和列表推导式类似,字典的元素是成对出现的,所以推导式定义的回收也是成对生成键值对

d1 = {n: n ** 2 for n in range(5)}
print(d1) # {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}

d2 = {v: k for k, v in d1.items()}
print(d2) # {0: 0, 1: 1, 4: 2, 9: 3, 16: 4}

6.3 集合推导式

集合推导式和列表推导式基本没什么区别,但是集合推导式会帮我们去除重复的元素,并且不适用中括号,而是使用花括号

s1 = {i ** 2 for i in [-1, -5, 1, 2, -2]}
print(s1) # {1, 4, 25}

文章作者: Soulballad
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Soulballad !
评论
 上一篇
【Python】-3.Python中的流程控制 【Python】-3.Python中的流程控制
所有编程语言在编写时都要遵循语言结构和流程控制,它们控制了整个程序运行的步骤。流程控制包括顺序控制、条件控制和循环控制。所谓控制顺序,就是按照正常的代码执行顺序,从上到下、从文件头到文件尾依次指定每条语句。 1. if判断1.1 if语
2020-09-05
下一篇 
【Python】-1.Python数据类型及运算符 【Python】-1.Python数据类型及运算符
1. 常见类型1.1 数字在Python中最数字是一种常见的类型。 1.1.1加减乘除运算print(3 + 2) # 5 print(8 - 6) # 2 print(16 - 3 * 2) # 10 print((17 - 2) / 5
2020-09-01
  目录