6月29日Python基础学习笔记——字典、集合、实操作业、分支结构、while 循环

文章目录


前言

本文为6月29日python基础学习笔记,分为五个章节:

  • 字典:特点、字典的创建、字典元素的访问、添加、删除,以及键值对存储的底层分析;
  • 集合:特点、集合的创建、删除,并集、交集、差集的运算;
  • 实操作业;
  • 分支结构:单分支、双分支以及多分支;
  • 循环结构:while 循环。

一、字典

1、特点

  • “键值对”的无序可变序列,字典中的每个元素都是一个键值对
  • 列表中,通过“下标数字”找到对应的对象。字典中通过“键对象”找到对应的“值对象”。
  • “键”是任意的不可变数据,比如:整数、浮点数、字符串、元组。列表、字典、集合这些可变对象,不能作为“键”。 并且“键”不可重复
  • “值”可以是任意的数据,并且可重复。

2、字典的创建

(1)、通过 {}、dict() 创建

a = {'name':'gaoqi','age':18,'job':'programmer'}
a
>>> {'name': 'gaoqi', 'age': 18, 'job': 'programmer'}

b = dict(name='gaoqi', age=18, job='programmer')
b
>>> {'name': 'gaoqi', 'age': 18, 'job': 'programmer'}

c = dict([("name", "gaoqi"), ("age", 18)])
c
>>> {'name': 'gaoqi', 'age': 18}

(2)、通过 zip() 创建

k = ['name','age','job']
v = ['gaoqi',18,'teacher']
d = dict(zip(k, v)) # k 作为“键”,v 作为“值”
d
>>> {'name': 'gaoqi', 'age': 18, 'job': 'teacher'}

(3)、通过 .fromkeys() 创建值为空的字典

a = dict.fromkeys(['name', 'age', 'job'])
a
>>> {'name': None, 'age': None, 'job': None}

3、字典元素的访问

(1)、通过 [键] 获得“值”

若键不存在,则抛出异常。

a = {'name':'gaoqi','age':18,'job':'programmer'}

a['name']
>>> 'gaoqi'

a['gender']
>>> Traceback (most recent call last):
  File "<pyshell#14>", line 1, in <module>
    a['gender']
KeyError: 'gender'

(2)、通过 .get() 获得“值”

  • ==推荐使用。==指定键不存在时,返回 None;
  • 也可以设定指定键不存在时默认返回的对象。
a = {'name':'gaoqi','age':18,'job':'programmer'}

a.get('name')
>>> 'gaoqi'

a.get('gender')
>>>

a.get('gender', '男')
>>> '男'

(3)、.items() 列出所有的键值对

a = {'name':'gaoqi','age':18,'job':'programmer'}

a.items()
>>> dict_items([('name', 'gaoqi'), ('age', 18), ('job', 'programmer')])

(4)、.keys() 列出所有键 & .values() 列出所有值

a = {'name':'gaoqi','age':18,'job':'programmer'}

a.keys()
>>> dict_keys(['name', 'age', 'job'])

a.values()
>>> dict_values(['gaoqi', 18, 'programmer'])

(5)、检测一个“键”是否在字典中

a = {'name':'gaoqi','age':18,'job':'programmer'}

"name" in a
>>> True

3、字典元素添加

(1)、新增“键值对”

  • 如果“键”已经存在,则覆盖旧的键值对;
  • 如果“键”不存在,则新增“键值对”。
a = {'name':'gaoqi','age':18,'job':'programmer'}

a['address'] = '天安门广场'
a['age'] = 23
a
>>> {'name': 'gaoqi', 'age': 23, 'job': 'programmer', 'address': '天安门广场'}

(2)、.update()

将新字典中==所有键值对全部添加到旧字典对象上。==如果 key 有重复,则直接覆盖。

a = {'name':'gaoqi','age':18,'job':'programmer'}
b = {'name':'gaoxixi','money':1000,'sex':'男的'}

a.update(b)

a
>>> {'name': 'gaoxixi', 'age': 23, 'job': 'programmer', 'address': '天安门广场', 'money': 1000, 'sex': '男的'}

4、字典元素删除

(1)、del()

a = {'name':'gaoqi','age':18,'job':'programmer'}
del(a['name'])

a
>>> {'age': 18, 'job': 'programmer'}

(2)、clear()

删除所有键值对。

(3)、.pop()

删除指定键值对,并返回对应的“值对象”。

a = {'age': 18, 'job': 'programmer'}

b = a.pop('age')
b
>>> 18

(4)、.popitem()

随机删除和返回该键值对。因为字典是“无序可变序列”, 没有第一个元素、最后一个元素的概念。

a = {'name':'gaoqi','age':18,'job':'programmer'}

a.popitem()
>>> ('job', 'programmer')

a.popitem()
>>> ('age', 18)

a.popitem()
>>> ('name', 'gaoqi')

a
>>> {}

5、序列解包

  • 序列解包用于字典时,默认是对 “键” 进行操作。
s = {'name':'gaoqi','age':18,'job':'teacher'}

job, name, age = s # 让键 'name'对应 18、键 'age' 对应 'teacher'、键 'job' 对应 'gaoqi'

job
>>> 'name'

name
>>> 'age'

age
>>> 'job'
  • 使用 .items()键值对操作
s = {'name':'gaoqi','age':18,'job':'teacher'}

job, name, age = s.items()

name
>>> ('age', 18)

age
>>> ('job', 'teacher')

job
>>> ('name', 'gaoqi')
  • 使用 .values()键值对操作
s = {'name':'gaoqi','age':18,'job':'teacher'}

job, name, age = s.values()

name
>>> 18

age
>>> 'teacher'

job
>>> 'gaoqi'

6、表格数据使用字典和列表存储,并实现访问

姓名年龄薪资城市
高小一1830000北京
高小二1920000上海
高小五2010000深圳
# 表格数据使用字典和列表存储,并实现访问

r1 = {"name": "高小一","age": 18,"salary": 30000,"city": "北京"} # 表格第一行
r2 = {"name": "高小二","age": 19,"salary": 20000,"city": "上海"}
r3 = {"name": "高小五","age": 20,"salary": 10000,"city": "深圳"}

table = [r1, r2, r3]

# 获得高小二的薪资
print(table[1].get('salary'))
>>> 20000

# 获得所有人的薪资
for i in range(len(table)):
    print(table[i].get('salary'))
>>> 30000
>>> 20000
>>> 10000

# 打印表的所有数据
for i in range(len(table)):
    print(table[i].items())
>>> dict_items([('name', '高小一'), ('age', 18), ('salary', 30000), ('city', '北京')])
>>> dict_items([('name', '高小二'), ('age', 19), ('salary', 20000), ('city', '上海')])
>>> dict_items([('name', '高小五'), ('age', 20), ('salary', 10000), ('city', '深圳')])

7、字典核心底层原理

  • 字典对象的核心是散列表。散列表是一个稀疏数组(总是有空白元素的数组)
  • 数组的每个单元叫做 bucket
  • 每个 bucket 有两部分
    1. 键对象的引用;
    2. 值对象的引用。
  • 所有 bucket 结构和大小一致,可通过偏移量来读取指定 bucket。
    bucket

(1)、将一个键值对放进字典的底层过程

把”name” = ”xiaoli”这个键值对放到字典对象 a 中

a = {}
a[“name”] = “xiaoli”

  • 假设字典 a 对象创建完后,数组长度为 8。
    数组长度8
  • 第一步: 需要计算键 name 的散列值,通过 hash() 来计算。
bin(hash("name")) #计算键 name 的散列值并转换成二进制
>>> '0b100101101100011011101011010011001010001000101100110110010001111'
  • 数组长度为 8(23,我们可以拿计算出的散列值的最右边 3 位数字(111)作为偏移量, 十进制是数字 7。
  • 查看偏移量 7对应的 bucket 是否为空:
    • 如果为则将键值对放进去;
    • 如果不为空则依次取左边 3 位作为偏移量,即“001”,十进制是数字 2。再查看偏移量为 2 的 bucket 是否为空。直到找到为空的 bucket 将键值对放进去。
Created with Raphaël 2.3.0 计算键对象的散列值 0b100101101100011011101011010011001010001000101100110110010001111 数组长度为 8,则取散列值最右侧 3位二进制数(111 = 索引 7 的bucket 为空 存储键值对到空的 bucket 依次再取左侧 3位二进制数 对应索引的 bucket 为空 yes no yes no
  • 扩容: python 会根据散列表的拥挤程度扩容,即创造更大的数组,将原有内容拷贝到新数组中。 接近 2/3 时,数组就会扩容。

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

a = {}
a["name"] = "xiaoli"

a.get("name")
>>> 'xiaoli'
  • 和存储的底层流程算法一致,也是依次取散列值的不同位置的数字。
  • 假设数组长度为 8,将散列值最右边 3 位数字作为偏移量,即“111”,十进制数字 7。查看偏移量 7,对应的 bucket 是否为空:
    • 如果为,则返回 None
    • 如果不为空则将这个 bucket 的键对象的散列值,和我们的散列值进行比较:
      • 如果相等。则返回对应“值对象”;
      • 如果不相等,则再依次取左侧数字,重新计算偏移量。依次取完后,仍然没有找到。则返回 None。
Created with Raphaël 2.3.0 计算键对象的散列值 0b100101101100011011101011010011001010001000101100110110010001111 数组长度为 8,则取散列值最右侧 3位二进制数(111 = 对应索引的 bucket 为空 返回 None 取出该 bucket 中的键,并计算散列值 B 两个散列值相等 返回该 bucket 对应的值对象 依次再取散列值左侧3位二进制数 yes no yes no

二、集合

1、特点

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

2、 集合的创建

(1)、通过 {} 创建,并使用 .add() 添加元素

a = {3, 5, 7}

a
>>> {3, 5, 7}

a.add(9)
a
>>> {9, 3, 5, 7}

(2)、set()

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

a = ['a','b','c','b']

b = set(a)
b
>>> {'b', 'a', 'c'}

3、 集合的删除

(1)、.remove()

a = {10,20,30,40,50}

a.remove(20)
a
>>> {50, 40, 10, 30}

(2)、.clear()

清空整个集合。

4、 集合的并集、交集、差集

a = {1,3,'sxt'}
b = {'he','it','sxt'}

a | b # a.union(b)
>>> {1, 'sxt', 3, 'it', 'he'}

a & b # a.intersection(b)
>>> {'sxt'}

a - b # a.difference(b)
>>> {1, 3}

三、实操作业

1、画出代码 a = [100,200,300]的内存存储示

列表存储

2、使用 range 生成序列:30,40,50,60,70,80

a = list((x+3)*10 for x in range(6))

a
>>> [30, 40, 50, 60, 70, 80]

3、推导式生成列表: a = [x*2 for x in range(100) if x%9==0],手写出结果

[0, 18, 36, 54, 72, 90, 108, 126, 144, 162, 180, 198]

4、使用二维列表存储表格信息,并画出简单的内存存储示意图

表

a = [ ["高小一", 18, 30000, "北京"],
      ["高小二", 19, 20000, "上海"],
      ["高小五", 20, 10000, "深圳"]]

二维列表存储

5、列表和元组的相同点与不同点

  • 列表:可变,可以任意修改列表中的元素;可存储任意数目、类型的数据;大小可变;
  • 元组:不可变,不能修改元组中的元素。

6、创建一个字典对象,包含如下信息:支出金额:300.15,支出日期:2018.10.18,支出人:高小七

b = ['支出金额', '支出日期', '支出人']
c = [300.15, '2018.10.18', '高小七']

d = dict(zip(b, c))
d
>>> {'支出金额': 300.15, '支出日期': '2018.10.18', '支出人': '高小七'}

7、使用字典存储行数据,最后将整个表使用列表存储起来

row1 = {"高小一", 18, 30000, "北京"}
row2 = {"高小二", 19, 20000, "上海"}
row3 = {"高小五", 20, 10000, "深圳"}

li = [row1, row2, row3]
li
>>> [{30000, 18, '北京', '高小一'}, {20000, 19, '上海', '高小二'}, {10000, '深圳', '高小五', 20}]

8、用文字和自己画的示意图描述:字典存储一个键值对的底层过程

假设字典对象创建完后,数组长度为 8(23)。

  1. 使用 bin() 函数和 hash() 函数计算“键”的散列值;
  2. 取该散列值最右侧三位数的十进制数作为偏移量,查看该偏移量相对应的 bucket 是否为空:
    • 若为空,则将键值对放进去;
    • 若不为空,则往左侧取三位,以这三位的十进制数作为偏移量,再次查看该偏移量相对应的 bucket 是否为空。直到找到空的 bucket 将键值对放进去。
      字典存储底层

9、集合和字典有什么关系?

集合的底层是字典实现的,即集合的所有元素都是字典中的“键”。


四、分支结构

选择和循环结构中,条件表达式的值为 False 的情况如下:

  • False;
  • 0、0.0;
  • None;
  • 空序列对象;
  • 空 range 对象;
  • 空迭代对象。
    其他情况,均为 True。
    条件表达式中,不能有赋值操作符“=”。

1、单分支结构

单分支

num = input("输入一个数字:")
if int(num)<10:
	print(num)

2、双分支结构

双分支

num = input("输入一个数字:")
if int(num)<10:
	print(num)
else:
	print("数字太大")
  • 三元条件运算符:
num = input("请输入一个数字")
print( num if int(num)<10 else "数字太大")

3、多分支结构

多分支

(1)、方法 1

score = int(input("输入分数:"))
grade = ""
if score<60:
    grade = "不及格!"
elif score<80:
    grade = "及格"
elif score<90:
    grade = "良好"
else:
    grade = "优秀!"

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

(2)、实操:已知点的坐标(x,y),判断其所在的象限

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("第四象限")

(3)、选择结构嵌套

score = int(input("输入分数:"))
grade = ""

if score>100 or score<0:
    print("输入的分数不正确")
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))

五、循环结构

循环结构

1、while 循环

  • 利用 while 循环打印从 0-10 的数字:
num = 0
while num<=10:
    print(num, end="\t")
    num += 1

0	1	2	3	4	5	6	7	8	9	10
  • 利用 while 循环,计算 1-100 之间数字的累加:
num2 = 0
sum = 0

while num2 in range(101):
    sum = sum + num2
    num2 += 1

print("1-100的和为:", sum)

>>> 1-100的和为: 5050

总结

  1. 键必须为可散列:
    • 数字、字符串、元组都是可散列的;
    • 自定义对象需要支持下面三点:
      • 支持 hash() 函数;
      • 支持通过 __eq__() 方法检测相等性;
      • a==b 为真,则==hash(a)==hash(b)==也为真。
  2. 字典在内存中开销巨大,典型的空间换时间;
  3. 键查询速度很快;
  4. 往字典里面添加新键可能导致扩容,使键的次序变化。因此,不要在遍历字典的同时进行字典的修改。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值