六、重要数据类型

六、重要数据类型

6.1、列表

6.1.1、列表声明

在实际开发中,经常需要将一组(不只一个)数据存储起来,一边后边的代码使用。列表就是这样的一个数据结构。

列表会将所有元素都放在一对中括号[]里面 相邻元素之间用逗号,分隔,如下所示:

# 列表的构建 语法构建[数据对象, ... ,]
# 特点1: 列表中的元素可以时任意数据类型
# 特点2: 列表中的元素个数没有限制

[element1, element2, element3, ..., elementn]

 

不同于Cjava等语言的数组,python的列表可以存放不同的,任意的数据类型对象。

l =[123,"hao",True]
print(l.type(l))


# 注意
a.b = [1.2]
print(a,b)

6.1.2、序列操作

列表是Python序列的一种,我们可以使用索引(index)访问列表中的某个元素(得到的是一个元素的值),也可以用切片访问列表中的一组元素(得到的是一个新的子列表)。

 

  •  索引求值
print(l[2]) # 12
print(l[-1]) # 14
  • 切片操作
复制代码
l = [10,11,12,13,14]
print(l[2:5])
print(l[-3:-1])
print(l[:3])
print(l[1:])
print(l[:])
print(l[2:4])
print(l[-3:-1])
print(l[-1:-3])
print(l[-1:-3:-1])
print(l[::2])
复制代码

1、取出的元素数量为:结束位置 - 开始位置;

2、取出元素不包含结束位置对应的索引,列表最后一个元素使用 list[len(slice)] 获取;

3、当缺省开始位置时,表示从连续区域开头到结束位置;

4、当缺省结束位置时,表示从开始位置到整个连续区域末尾;

5、两者同时缺省时,与列表本身等效;

6、step为正,从左向右切,为负从右向左切。

  • 判断成员是否存在

in 关键字检查某元素是否为序列的成员

l = [10,11,12,13,14]
print(20 in l) # Falase
print(12 in l)  # True
  • 相加
l1 = [1,2,3]
l2 = [4,5,6]
print(l1 + l2) # [1,2,3,4,5,6]
  • 循环列表
复制代码
for name in ["张三","李四","王五"]:
    print(name)

for i in range(10): # range函数: range(start,end,step)
    print(i)

# 基于for循环从100打印到1
for i in  range(100,0,-1):
    print(i)
复制代码

6.1.3、列表内置方法

l = [1,2,3]
方法作用示例结果
append() 向列表追加元素 l.append(4) l:[1, 2, 3, 4]
insert() 向列表任意位置添加元素 l.insert(0,100) l:[100, 1, 2, 3]
extend() 向列表合并一个列表 l.extend([4,5,6]) l:[1, 2, 3, 4, 5, 6]
pop() 根据索引删除列表元素(为空删除最后一个元素) l.pop(1) l:[1, 3]
remove() 根据元素值删除列表元素 l.remove(1) l:[2, 3]
clear() 清空列表元素 l.clear() l:[]
sort() 排序(升序) l.sort() l:[1,2,3]
reverse() 翻转列表 l.reverse() l:[3,2,1]
count() 元素重复的次数 l.count(2) 返回值:1
index() 查找元素对应索引 l.index(2) 返回值:1
复制代码
# 列表的内置方法: 列表对象.方法()
# 列表的内置方法是用来管理列表中的数据:增删改查

#
增删改查: [].方法() # (1) ******************************** 增(append,insert,extend) **************** l1 = [1, 2, 3] # append方法:追加一个元素 l1.append(4) print(l1) # [1, 2, 3, 4] # insert(): 插入,即在任意位置添加元素 l1.insert(1, 100) # 在索引1的位置添加元素100 print(l1) # [1, 100, 2, 3, 4] # 扩展一个列表:extend方法 l2 = [20, 21, 22, 23] # l1.append(l2) l1.extend(l2) print(l1) # [1, 100, 2, 50, 3, 4,[20,21,22,23]] # 打印列表元素个数python内置方法: print(len(l1)) # (2) ******************************** 删(pop,remove,clear) ********************** l4 = [10, 20, 30, 40, 50] # 按索引删除:pop,返回删除的元素 # ret = l4.pop(2) # print(ret) # print(l4) # [10, 20, 40, 50] # 按着元素值删除 l4.remove(30) print(l4) # [10, 20, 40, 50] # 清空列表 l4.clear() print(l4) # [] # (3) ******************************** 修改(没有内置方法实现修改,只能基于索引赋值) ******** l5 = [10, 20, 30, 40, 50] # 将索引为1的值改为200 l5[1] = 200 print(l5) # [10, 200, 30, 40, 50] # 将l5中的40改为400 ,step1:查询40的索引 step2:将索引为i的值改为400 i = l5.index(40) # 3 l5[i] = 400 print(l5) # [10, 20, 30, 400, 50] # (4) ******************************** 查(index,count,sort) ******************************* l6 = [10, 50, 30, 20, 40, 10]
print(l6.count(10)) # 2 # 会从左向右一次统计出现的值的次数 l6.reverse()
# 只是翻转 [40, 20, 30, 50, 10, 10] print(l6) # [] # # 查询某个元素的索引,比如30的索引 # print(l6.index(30)) # 2 # 排序 # l6.sort(reverse=True) # print(l6) # [50, 40, 30, 20, 10,10]
复制代码

6.1.5、深浅拷贝

深浅拷贝时Python中经常涉及到一个面试,也是经常出错的地方。那么什么是深浅拷贝呢?

复制代码
# 案例1:变量赋值
l1 = [1,2,3]
l2 = l1 # 不是拷贝,完全指向一块内存空间
print(id(l1))
print(id(l2))
l2[1] = 200
print(l1)

# 案例2
l1 = [1, 2, 3]
l2 = [4, 5, l1]
l1[0] = 100
print(l2)

# 案例3:浅拷贝:两种方式:切片和copy方法
l1 = [1,2,3,["yuan","alvin"]]
l2 = l1.copy()  # 等同于l2 = l1[:]
print(id(l1))
print(id(l2))
l2[1] = 200
print(l1)
l2[3][0] = "张三"
print(l1)

#案例4: 深拷贝
import copy
l1 = [1,2,3,["yuan","alvin"]]
l2 = copy.deepcopy(l1)
l2[3][0] = "张三"
print(l1)
复制代码

6.1.6、列表生成式

列表生成式即List Comprehensions,是Python内置的非常简单却强大的可以用来创建的list的生成式。

复制代码
# for循环:遍历循环,循环次数取决于遍历对象的元素个数
variable = [表达式 for 迭代变量 in 可迭代对象 [if 条件表达式]]
"""
for 循环的格式:

for 变量 in 可迭代对象(字符串|列表|字段|元祖|集合):
循环体
"""

复制代码

 

[if 条件表达式] 不是必须的,可以使用,也可以省略。

例如: 计算1-100中所有偶数的平方

# 计算1-100中所有偶数的平方
new_l = [i * i for i in range(100) if i % 2 ==0]
print(new_l)

以上所看到的的列表推导式都只有一个循环,实际上他可以使用多个循环,就像循环一样。

练习1:

 

old = [[1, 2], [3, 4], [5, 6]]
# 从old中一个一个取出值,对取出的值, (i)在进行一次遍历取值操作(也可以进行判断或者运算)
new = [j for i in old for j in i]
print(new) # [1, 2, 3, 4, 5, 6]

6.2元祖

6.2.1、声明元祖

Python的元祖与列表类似,不同之处在于元祖的元素只能读,不能修改。通常情况下,元祖用于保存无需修改的内容。

元祖使用小括号,声明一个元祖。

(element1, element2, element3, ..., elementn)

需要注意的一点事,当创建的元祖中只有一个字符串类型的元素时,改元素后面必须加一个逗号,  ,否则Python解释器会将它视为字符串。

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

6.2.2、序列操作

和列表一样,支持索引和切片操作

num = (1, 2, 3, 4, 5)
print(num[2]) # 3
print(num[2:4]) # (3, 4)
print(num[:4]) # (1, 2, 3, 4)
print(2 in num) # True

6.2.3、内置方法

num = (1, 2, 3, 4, 5)
print(num.count(3)) #  统计3在这个元祖出现的次数
print(num.index(2)) #  查看num索引的位置

6.3、字典

字典是Python提供的唯一内建的映射(Mapping Type)数据类型

6.3.1、声明字典

Python使用{}创建字典,由于字典中每个元素都包含键(key) 和值(value) 两部分,因此在创建字典时,键和值之间使用冒号:分隔,相邻元素之间使用逗号,分隔,所以元素放在大括号{}中

使用{}创建字典的语法格式如下:

dictname = {"key":"value","key2":"value2",...}

1、同一字典中的各个键必须唯一,不能重复。

2、字典是键值对是无序的,但在3.6版本后,字典默认做成有序的了,这是新的版本特征。

3、字典的键必须是一个不可变的数据类型(除了列表和字典数据类型),常用的就是字符串和整数

4、字典的值可以时任意数据类型

5、字典的键值对原则上是没有限制的

6.3.2、字典的基本操作

 

复制代码

# 一 通过键查询值 列表对象[索引] 字典对象[键]
#
(1)查件键值 print(book["title"]) # 返回字符串 西游记 print(book["authhors"]) # 返回列表 ['吴承恩','wuchengen'] # (2)添加或修改键值对,注意:如果存在。则是修改,否则是添加 book["price"] = 209 # 修改键的值 book["publish"] = "北京出版社" # 添加键值对 # (3)删除键值对 del 删除命令 print(book) del book["publish"] print(book) del book print(book) # (4) 判断键是否存在某字典中 print("price" in book) # (5) 循环 for key in book print(key,book[key])
复制代码

6.3.3、字典的内置方法

d = {"name":"hao":"age":18}
方法作用示例结果
get() 查询字典某键的值,取不到返回默认值 d.get("name",None) "hao"
setdefault() 查询字典某键的值,取不到给字典设置键值,同时返回设置的值 d.setdefault("age",20) 18
keys() 查询字典中所有的键 d.keys() ['name','age']
values() 查询字典中所有的值 d.values() ['hao', 18]
items() 查询字典中所有的键和值 d.items() [('name','hao'), ('age', 18)]
pop() 删除字典指定的键值对 d.pop(“age”) {'name':'hao'}
popitem() 删除字典最后的键值对 d.popitem() {'name':'hao'}
clear() 清空字典 d.clear() {}
update() 更新字典 t={"gender":"male","age":20}d.update(t) {'name':'hao','age': 20, 'gender': 'male'}
复制代码
dic = {"name": "hao", "age": 22, "sex": "male"}

# (1)查字典的键的值

print(dic["names"])  # 会报错
name = dic.get("names")
sex = dic.get("sexs", "female")
print(sex)
print(dic.keys())  # 返回值:['name', 'age', 'sex']
print(dic.values())  # 返回值:['hao', 22, 'male']
print(dic.items())  # [('name', 'hao'), ('age', 22), ('sex', 'male')]

# setdefault取某键的值,如果能取到,则返回该键的值,如果没有改键,则会设置键值对
print(dic.setdefault("name"))  # get()不会添加键值对 ,setdefault会添加
print(dic.setdefault("height", "180cm"))
print(dic)

# (2)删除键值对 pop popitem

sex = dic.pop("sex")  # male
print(sex)  # male
print(dic)  # {'name': 'hao', 'age': 22}

dic.popitem()  # 删除最后一个键值对
print(dic)  # {'name': 'hao'}

dic.clear()  # 删除键值对

# (3) 添加或修改 update
add_dic = {"height": "180cm", "weight": "60kg"}
dic.update(add_dic)
print(dic)  # {'name': 'hao', 'age': 22, 'sex': 'male', 'height': '180cm', 'weight': '60kg'}

update_dic = {"age": 33, "height": "180cm", "weight": "60kg"}
dic.update(update_dic)
print(dic)  # {'name': 'hao', 'age': 33, 'sex': 'male', 'height': '180cm', 'weight': '60kg'}

# (4) 字典的循环

dic = {"name": "hao", "age": 22, "sex": "male"}

# 遍历键值对方式1
# for key in dic:  # 将每个键分别赋值给key
#     print(key, dic.get(key))

# 遍历键值对方式2

# for i in dic.items(): # [('name', 'hao'), ('age', 22), ('sex', 'male')]
#     print(i[0],i[1])


# 关于变量补充
# x = (10, 20)
# print(x, type(x))  # (10, 20) <class 'tuple'>
# x, y  = (10, 20)
# print(x, y)

for key, value in dic.items():
    print(key, value)
复制代码

6.3.4、字典的进阶使用

字典属于可变数据类型

 

复制代码
# 案例1
stu01 = {"name":"rain"}
stus = {1001: stu01}
print(stus)
stus["name"] = "hao"
print(stus)
print(id(stus[1001]))
stus[1001] = {"name": "xiao"}
print(stu01)
print(id(stus[1001]))


# 案例2
students_dict = {}
scores_dict = {
    "chinese": 100,
    "math": 90,
    "english": 50,
}

stu_dic = {
    "name": "rain",
    "scores": scores_dict
} 

students_dict[1002] = stu_dic
print(students_dict)
scores_dict["math"] = 0
print(students_dict)
复制代码

 

复制代码
# 案例1: 列表存放字典

data = [
    {"name": "rain", "age": 22},
    {"name": "hao", "age": 32},
    {"name": "xiao", "age": 24},
]

# 循环data, 每行按着格式 [姓名: rain,年龄:22]。 将每个学生的信息逐行打印


for stu_dic in data:  # data是一个列表
    # print(stu_dic)
    print("「姓名: %s,年龄:%s』" % (stu_dic.get("name"), stu_dic.get("age")))

# 将data中第二个学生的年龄查询出来

print(data[1].get("age"))

# 案例二
data2 = {
    1001: {"name": "ranin", "age": 22},
    1002: {"name": "xiao", "age": 32},
    1003: {"name": "hao", "age": 24},
}

# 循环data2,每行按着格式『学号1001, 姓名:rain,年龄:22』将每个学生的信息逐行打印

for stu_id, stu_dic in data2.items():
    # print(stu_id, stu_dic)
    name = stu_dic.get("name")
    age = stu_dic.get("age")
    print("「学好」: %s,姓名 %s,年龄: %s" % (stu_id, name, age))


#「姓名: rain,年龄:22』
# 「姓名: hao,年龄:32』
# 「姓名: xiao,年龄:24』
# 32
# 「学好」: 1001,姓名 ranin,年龄: 22
# 『学号: 1001, 姓名 ranin,年龄:22』
# 「学好」: 1002,姓名 xiao,年龄: 32
# 『学号: 1002, 姓名 xiao,年龄:32』
# 「学好」: 1003,姓名 hao,年龄: 24
# 『学号: 1003, 姓名 hao,年龄:24』
复制代码

6.3.5、字典生成式

同列表生成式一样,字典生成式是用来快速生成字典的。通过直接使用一句代码来指定要生成字典的条件及内容替换了使用多行条件或者是多行循环代码的传统方式。

 格式:
{字典内容+循环条件+判断条件}
stu = {"id": "1001", "name": "hao", "age": 22, "score": 100, "weight": "50kg"}
stu = {k: v for k, v in stu.items() if k == "score" or k == "name"}
print(stu) # {'name': 'hao', 'score': 100}

练习:将一个字典的键值倒换

dic = {"1": 1001, "2": 1002, "3": 1003}
new_dic = {v: k for k, v in dic.items()}
print(new_dic) # {1001: '1', 1002: '2', 1003: '3'}

练习:将所有的key值变为大写

print({k.upper():v for k,v in dic.items()}) # {'1': 1001, '2': 1002, '3': 1003}

6.3.5、字典的hash存储

hash:百度百科

Hash,一般翻译做散列、杂凑,或音译为哈希,是把任意长度的输入(又叫做预映射pre-image)通过散列算法变换成固定长度的输出,该输出就是散列值。这种转换是一种压缩映射,也就是,散列值的空间通常远小于输入的空间,不同的输入可能会散列成相同的输出,所以不可能从散列值来确定唯一的输入值。简单的说就是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数。

字典对象的核心其实是个散列表,而散列表是一个稀疏数组(不是每个位置都有值),每个单元叫做bucket,每个bucket有两部分:一个是键对象的引用,一个是值对象的引用,由于,所有bucket结构和大小一致,我们可以通过偏移量来指定bucket的位置

 

  将一对键值放入字典的过程:

先定义一个字典:在写入值

d = {}
d["name"] = "hao"

在执行第二行时,第一步就是计算"name"的散列值,Python中可以用hash函数得到hash值,再将得到的值放入bin函数,返回int类型的二进制

print(bin(hash("name")))

结果为:

0b110001110010001111000001011101101101110001000000001101110000010

假设数组长度为10,我们取出计算出的散列值,最右边3位数作为偏移量,即100,十进制是数字4,我们查看偏移量为4对应的bucket的位置是否为空,如果为空,则将键值放进去,如果不为空,依次取右边3位作为偏移量101,十进制是数字5,再查看偏移量5的bucket是否为空,直到单元为空的bucket将键值放进去。以上就是字典的存储原理。

当进行字典查询时:

d["name"]
d.get("name")

第一步与存储一样,先计算键的散列值,取出后三位111,十进制为4的偏移量,找到对应的bucket的位置,查看是否为空,如果为空就返回None,不为空就获取键并计算键的散列值,计算后将刚计算的散列值与要查询的键的散列值比较,相同就返回对应bucket位置的value,不同就往前再取三位重新计算偏移量,依次取完后还是没有结果就返回None

 6.4、集合

Python 中的集合,和数学中的集合概念一样。由不同可hash的不重复的元素组成的集合。

 
{element1,element2,...}

6.4.1、声明集合

Python 集合会将所有元素放在一对大括号 {} 中,相邻元素之间用“,”分隔,如下所示:

{element1,element2,...}

其中,elementn 表示集合中的元素,个数没有限制。

从内容上看,同一集合中,只能存储不可变的数据类型,包括整形、浮点型、字符串、元组,无法存储列表、字典、集合这些可变的数据类型,否则 Python 解释器会抛出 TypeError 错误。

由于集合中的元素是无序的,因此无法向列表那样使用下标访问元素。Python 中,访问集合元素最常用的方法是使用循环结构,将集合中的数据逐一读取出来。

s = {"zhangsan",18,"male"}
for item in s:
    print(item)

6.4.2、内置方法

a = {1,2,3}
b = {3,4,5}
 
方法作用示例结果
add() 向集合添加元素 a.add(4) {1, 2, 3, 4}
update() 向集合更新一个集合 a.update({3,4,5}) | {1, 2, 3, 4, 5}` |  
remove() 删除集合中的元素 a.remove(2) {1, 3}
discard() 删除集合中的元素 a.discard(2) {1, 3}
pop() 随机删除集合一个元素 a.pop() {2,3}
clear() 清空集合 a.clear() {}
intersection() 返回两个集合的交集 a.intersection(b) {3}
difference() 返回两个集合的差集 a.difference(b)b.difference(a) {1,2}{4,5}
symmetric_difference() 返回两个集合的对称差集 a.symmetric_difference(b) {1, 2, 4, 5}
union() 返回两个集合的并集 a.union(b) {1, 2, 3, 4, 5}

 

posted @   xiaohaoge  阅读(162)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
点击右上角即可分享
微信分享提示