python字典实现原理_python学习笔记_第7天(字典底层原理+选择结构)

字典:(拓展–重要)字典核心底层原理

字典对象的核心是散列表,散列表是一个稀疏数组(总是有空白元素的数组),数组的每个单元叫做bucket。

每个bucket 有两部分:一个是键对象的引用,一个是值对象的引用。又因所有bucket 结构和大小一致,就可以通过偏移量来读取指定bucket。

b5f0aae28ad1bdb43d18e816e9a64327.png

将一个键值对放进字典的底层过程

创建一个空字典,假设字典a 对象创建完后,数组长度为8。

37d307bf7aad2b7d8cc99e367d4ab0b8.png

创建一个键值对"name"=“张三”,把这个键值对放到字典对象a中第一步需要计算键”name”的散列值。Python 中可以通过hash()来计算。

a = {}

a["name"]="张三"

bin(hash("name")) # '-0b1010111101001110110101100100101'

前假设数组长度为8,偏移量(索引)0-7可用二进制数000-111表示。此时可将散列值的最右边3位数字作为偏移量,即101=5。查看偏移量5对应的bucket 是否为空,为空则存放键值对,不为空则依次取右边3位作为偏移量,如100=4。再查看偏移量为4的bucket是否为空,直到找到为空的bucket 将键值对存放进去。当存放多个键值对散列表的拥挤接近2/3时,数组就会扩容(创造更大的数组,将原有内容拷贝到新数组中。)流程图如下:

508590f53886146db03cf795db0c8e0b.png

根据键查找“键值对”的底层过程

调用a.get(“name”),根据键“name”查找到“键值对”,从而找到值对象。先计算“name”对象的散列值: ‘-0b1010111101001110110101100100101’。假设数组长度为8,拿计算出的散列值最右边3位数字作为偏移量,即101=5,查看偏移量5对应的bucket是否为空。如果为空则返回None,不为空则将这个bucket的键对象计算对应散列值,并和查找的散列值进行比较。如果相等则返回对应“值对象”,若不相等则再依次向前取数,重新计算偏移量并比较查找值的散列值。依次取完后仍然没有找到,则返None。流程图如下:

7b99e1edec62a59060ff120b2a81af17.png

总结:

键必须可散列,数字、字符串、元组,都是可散列的。

自定义对象需要支持下面三点:

支持hash()函数

支持通过__eq__()方法检测相等性

若a==b为真,则hash(a)==hash(b)也为真

字典键查询速度很快

字典在内存中开销巨大,是以空间换时间的典型

往字典里面添加新建可能导致扩容,从而导致散列表中键的次序变化。因此,不要在遍历字典的同时进行字典的修改。

集合

集合无序可变,但元素不能重复。实际上集合底层是字典实现,集合的所有元素都是字典中的“键对象”,因此唯一且不能重复。

集合的创建

{}创建集合

使用{}创建集合对象,并可用add()方法添加元素

a = {1,2,3}

a.add(6)

print(a) # {1, 2, 3, 6}

set()创建集合

set()可将列表、元组等可迭代对象转成集合。如果原来数据存在重复数据,则自动去重只保留一个。

a = [1,3,5,7,3,5]

b = set(a)

print(b) # {1, 3, 5, 7}

集合的删除

remove()删除指定元素;clear()清空整个集合

a = {1,2,3,4,5}

a.remove(4)

print(a) # {1, 2, 3, 5}

a.clear()

print(a) # set()

集合特有操作

集合特有并集、交集、差集等运算

a = {1,3,7,'a','c','e'}

b = {1,2,3,'a','b'}

# 并集

a|b # {'e', 1, 2, 3, 'a', 7, 'c', 'b'}

a.union(b) # {'e', 1, 2, 3, 'a', 7, 'c', 'b'}

# 交集

a&b # {1, 3, 'a'}

a.intersection(b) # {1, 3, 'a'}

# 差集

a-b # {'e', 'c', 7}

b-a # {'b', 2}

b.difference(a) # {'b', 2}

控制语句

选择结构

选择结构通过判断条件是否成立,来决定执行哪个分支,可分为单分支、双分支、多分支。

单分支选择结构

03dc9d7e28795d64d1b80b4011b63484.png

if 语句单分支结构的语法形式如下:

if 条件表达式:

语句/语句块

num = input("请输入一个数字:")

if int(num)<10: # input从外部读取的是字符串类型,需要通过int()转换成整形,判断逻辑表达式

print(num)

条件表达式:可以是逻辑表达式、关系表达式、算术表达式等等。不能出现赋值操作符“=”,会报错。可用关系运算符“==”。

语句/语句块:可以是一条语句,也可以是多条语句。多条语句,缩进必须对齐一致。

条件表达式的值为False 的情况

经过判断为False,Fales值,None值

数值:0,0.0

空序列对象(空列表、空元祖、空集合、空字典、空字符串)

空range 对象、空迭代对象

a = [] # 空列表,是False

if a:

print( "空列表,False" )

b = "False" # 非空字符串,是True

if b:

print("非空字符串,是True")

c = False

if c:

print("False,是False")

c = None

if not c:

print("None,是False")

双分支选择结构

f96e71d35312deb32571f5f4f625c83f.png

双分支结构的语法格式如下:

if 条件表达式:

语句1/语句块1

else:

语句2/语句块2

重点–三元条件运算符:

三元运算符,用在某些简单双分支赋值情况。三元条件运算符语法格式如下:

条件为真时的值 if 条件表达式 else 条件为假时的值

#普通双分支结构

num = input("输入一个数字:")

if int(num)<10:

print(num)

else:

print("数字大于等于10")

#简易三元条件结构

num = input("请输入一个数字:")

print( num if int(num)<10 else "数字大于等于10") # 真值 if 条件 else 假值

多分支选择结构

4c3316a42fa933fc1332a5e485383282.png

多分支结构,几个分支之间存在逻辑关系,不能随意颠倒顺序。

多分支选择结构的语法格式如下:

if 条件表达式1 :

语句1/语句块1

elif 条件表达式2:

语句2/语句块2

elif 条件表达式n :

语句n/语句块n

[else:

语句n+1/语句块n+1

]

x = int(input("请输入x坐标:"))

y = int(input("请输入y 坐标:"))

if (x == 0 and y == 0):

print("原点")

elif (x == 0):

print("y 轴")

elif (y == 0):

print("x 轴")

elif (x > 0 and y > 0):

print("第一象限")

elif (x < 0 and y > 0):

print("第二象限")

elif (x < 0 and y < 0):

print("第三象限")

else:

print("第四象限")

选择结构嵌套

选择结构可以嵌套,重点注意不同级别代码块的缩进量,因为缩进量决定了代码的从属关系。语法格式如下:

if 表达式1:

语句块1

if 表达式2:

语句块2

else:

语句块3

else:

if 表达式4:

语句块4

score = int(input("请输入一个在0-100 之间的数字:"))

grade = ""

if score > 100 or score < 0:

score = int(input("输入错误!请重新输入一个在0-100 之间的数字:"))

else:

if score >= 90:

grade = "A"

elif score >= 80:

grade = 'B'

elif score >= 70:

grade = 'C'

elif score >= 60:

grade = 'D'

else:

grade = 'E'

print("分数为{0},等级为{1}".format(score, grade))

# 应用字符串切片的方法

score = int(input("请输入一个在0-100 之间的数字:"))

degree = "ABCDE"

num = 0

if score > 100 or score < 0:

score = int(input("输入错误!请重新输入一个在0-100 之间的数字:"))

else:

num = score // 10

if num < 6:

num = 5

print("分数是{0},等级是{1}".format(score, degree[9 - num]))

分享到:

e4fd8adf40ea259a7342e1f815e04c48.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值