文章目录
前言
本文为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、表格数据使用字典和列表存储,并实现访问
姓名 | 年龄 | 薪资 | 城市 |
---|---|---|---|
高小一 | 18 | 30000 | 北京 |
高小二 | 19 | 20000 | 上海 |
高小五 | 20 | 10000 | 深圳 |
# 表格数据使用字典和列表存储,并实现访问
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 有两部分:
- 键对象的引用;
- 值对象的引用。
- 所有 bucket 结构和大小一致,可通过偏移量来读取指定 bucket。
(1)、将一个键值对放进字典的底层过程
把”name” = ”xiaoli”这个键值对放到字典对象 a 中
a = {}
a[“name”] = “xiaoli”
- 假设字典 a 对象创建完后,数组长度为 8。
- 第一步: 需要计算键 name 的散列值,通过 hash() 来计算。
bin(hash("name")) #计算键 name 的散列值并转换成二进制
>>> '0b100101101100011011101011010011001010001000101100110110010001111'
- 数组长度为 8(23),我们可以拿计算出的散列值的最右边 3 位数字(111)作为偏移量, 十进制是数字 7。
- 查看偏移量 7对应的 bucket 是否为空:
- 如果为空,则将键值对放进去;
- 如果不为空,则依次取左边 3 位作为偏移量,即“001”,十进制是数字 2。再查看偏移量为 2 的 bucket 是否为空。直到找到为空的 bucket 将键值对放进去。
- 扩容: python 会根据散列表的拥挤程度扩容,即创造更大的数组,将原有内容拷贝到新数组中。 接近 2/3 时,数组就会扩容。
8、根据键查找“键值对”的底层过程
a = {}
a["name"] = "xiaoli"
a.get("name")
>>> 'xiaoli'
- 和存储的底层流程算法一致,也是依次取散列值的不同位置的数字。
- 假设数组长度为 8,将散列值最右边 3 位数字作为偏移量,即“111”,十进制数字 7。查看偏移量 7,对应的 bucket 是否为空:
- 如果为空,则返回 None;
- 如果不为空,则将这个 bucket 的键对象的散列值,和我们的散列值进行比较:
- 如果相等。则返回对应“值对象”;
- 如果不相等,则再依次取左侧数字,重新计算偏移量。依次取完后,仍然没有找到。则返回 None。
二、集合
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)。
- 使用 bin() 函数和 hash() 函数计算“键”的散列值;
- 取该散列值最右侧三位数的十进制数作为偏移量,查看该偏移量相对应的 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
总结
- 键必须为可散列:
- 数字、字符串、元组都是可散列的;
- 自定义对象需要支持下面三点:
- 支持 hash() 函数;
- 支持通过 __eq__() 方法检测相等性;
- 若 a==b 为真,则==hash(a)==hash(b)==也为真。
- 字典在内存中开销巨大,典型的空间换时间;
- 键查询速度很快;
- 往字典里面添加新键可能导致扩容,使键的次序变化。因此,不要在遍历字典的同时进行字典的修改。