1.6 进阶与强化
文章目录
1.6.1 组包与拆包(重要)
1.组包
把多个数据变成一个,实际上以前赋值的时候就可以直接学到,只是没提,在等号右边放置多个数据,就能自动包装成元组。
from_key = 2, 5, 7, 8, 9
print(from_key, type(from_key))
输出
(2, 5, 7, 8, 9) <class 'tuple'>
2.拆包
相反地,如果左边变量数量是多个,则可以拆分右边对应容器的元素,但是谨记,变量数量必须等于元素数量,否则会报错,可以拆元组,列表,字典。
li = ["a", "b", "c", "d", 7]
a, b, c, d, e = li
print(a, b, c, d, e, type(a), type(e))
输出
a b c d 7 <class 'str'> <class 'int'>
上述为列表,元组拆分同理,但是字典略有不同,因为字典是键与键值对应的容器,如果用相同方法去拆分的话,拆出来的只有键。
dict01 = {"name": "tom", "age": 17, "sex": "female"}
a, b, c = dict01
print(a, b, c, type(a))
输出
name age sex <class 'str'>
如果想访问键值
print(a, dict01[a])
print(b, dict01[b])
print(c, dict01[c])
# 或者
for k, v in dict01.items():
print(k, v)
# 实际上 k, v 这一步就是拆包了,本来 in dict.items()所获得的是多个元组,此步等于拆包了元组。
3 组包与拆包的应用
1.交换变量的值
一般情况下我们要交换变量,一般都需要用一个辅助变量。
a = 10
b = 20
c = 0
c = a
a = b
b = c
print(a,b)
# 输出
20,10
而利用组包拆包,我们只要一步,
a = 10
b = 20
a, b = b, a
print(a,b)
2. 函数可以返回多个数,亦可以直接分配给多个变量
def fun_pack(num1,num2,num3):
num_sum = num1 + num2 + num3
num_ave = num_sum/3
return num_sum, num_ave
num_sum, num_ave = fun_pack(88, 98, 99)
print(num_sum, num_ave)
1.6.2 引用
1.引用
给一个变量赋值的时候,我们就把一个数值所在的内存地址,引用给了变量。我们可以用id()这个函数来查看每个变量引用的数据的地址。
2.引用指向改变
具体可以查看1.2变量和简单数据类型
3.函数传参是引用传递
def fun_id(num):
print("函数调用的时候", id(num))
a = 10
print("函数调用前", id(a))
fun_id(a)
print("函数调用后", id(a))
输出
函数调用前 140708111845312
函数调用的时候 140708111845312
函数调用后 140708111845312
1.6.3 可变类型与不可变类型
可变类型:在存储空间里可以直接修改的数据类型,在地址不变的情况下可以修改内容
- 列表(list)
- 字典(dict)
- 集合(set)
不可变类型:在存储空间里不可以直接修改的数据类型,在地址不变的情况下不可修改内容
- 数值类型 int, bool, float
- 字符串 str
- 元组 tuple
li = [1, 2, 3, 4]
print("改变之前的地址", id(li))
li[0] = 5
print("改变之后的地址", id(li))
a = 5
print("改变之前的地址", id(a))
a = 6
print("改变之后的地址", id(a))
str_001 = "hello world"
print("改变之前的地址:", id(str_001))
str_001 = str_001.upper()
print("改变之后的地址:", id(str_001))
输出
改变之前的地址 2046831353408
改变之后的地址 2046831353408
改变之前的地址 140708111845152
改变之后的地址 140708111845184
改变之前的地址: 3060999261744
改变之后的地址: 3060999259760
可以看到 字符串和整数在经过所谓的修改,实际上已经引向了新的地址,并不是原来的地址了。
注意,可变类型的,传递进入函数的时候,我们引用的依旧是这个地址。
这个时候,只要我们不重新声明变量,此时引用的就是外面的全局变量,不用声明也可以对其进行更改,但是一旦只要进行了变量赋值,就会有所改变,此时函数里的变量会变成局部变量,不会影响到外面的变量指向的值。
def cha_dict(list_01):
print(id(list_01))
list_01 = [1, 2, 3, 4, 5, 6]
print(id(list_01))
return list_01
a = [1, 2, 3, 4]
print(id(a))
char_dict(a)
print(a)
cha_dict(a)
print(id(a))
print(a)
输出
1675900223552
1675900223552
1675900223552
[1, 2, 3, 4, 5]
1675900223552
1675899165760
1675900223552
[1, 2, 3, 4, 5]
,可以看出只要没进行重新赋值,我们通过函数可以直接改变可变类型的引向的值,地址不变。其他的可变类型与不可变类型同理。
def char_str(str_01):
print(id(str_01))
str_01 += "002"
print(id(str_01))
return str_01
def cha_str(str_01):
print(id(str_01))
str_01 = "001002"
print(id(str_01))
return str_01
a = "001"
print(id(a))
char_str(a)
print(a)
cha_str(a)
print(id(a))
print(a)
输出
2257338010608
2257338010608
2257338010928
001
2257338010608
2257338010544
2257338010608
001
可以看出,其实有个很好判断的认识,任何不可变变量,当你想要获得改变或者删除的内容的时候,我们都要重新使用赋值这个来引出结果,此时获得的就是新的地址,但是在函数里,确实会获得新地址,却也同时变成了局部变量。
1.6.4 列表推导式
快速生成列表的表达形式,通过for添加元素的简洁写法。
类似切片,但是不能省略结束。
for in range(开始位置,结束位置,步长)
new_list = []
for i in range(5):
new_list.append(i)
print(new_list)
new_list2 = [i for i in range(5)]
new_list3 = [i for i in range(101) if i % 2 ==0]
new_list3 = [i*2 for i in range(101) if i % 2 ==0]
格式
[i(可进行计算) for i in range(范围+步长) if 判断]
1.6.5 匿名函数
匿名函数是简单函数的简洁写法,定义的函数没有名字。
lambda [形参1][形参2]````:[单行表达式] 或者函数调用
lambda主体是一个表达式,仅能在表达式里封装有限的逻辑,不能封装while,for循环。
lambda有自己的命名空间,且不能访问参数列表以外的参数。
lambda里不需要return,lambda自身表达式的结果就是函数返回结果,不可以不返回。如果想返回None得自己写None在表达式里。如果表达式里的函数没返回值的时候也是none
# 有参数有返回值的匿名函数,直接调用
ret = (lambda a, b: (a-b)*(a+b))(5, 4)
print(ret)
# 先给匿名函数命名再传参,有返回值
ave_grade = lambda chinese_grade, math_grade, english_grade: (chinese_grade + math_grade + english_grade) / 3
print("小明同学的考试平均分为:", ave_grade(98, 78, 100))
print("小花同学的考试平均分为:", ave_grade(95, 99, 90))
扩展
函数的参数是作为函数使用 匿名函数的应用
def foo(fn):
fn()
print(fn())
foo((lambda: 10 - 2))
# 可以看到foo函数的参数是函数,而我们此时可以快速的使用匿名函数进去被调用。
1.6.6 递归函数
如果一个函数在内部调用其本身,这个函数就是递归函数。
递归函数一般会在特定情况下不在调用函数本身(防止内存溢出),会提前给你报错,超出最大递归深度。正常情况下一定要有一个可以出口的点。
1.用递归函数做一个阶乘
def fun_factorial(n):
if n == 1:
return 1
else:
ret = n * fun_factorial(n - 1)
return ret
ret_10 = fun_factorial(10)
print("10的阶乘结果是:", ret_10)
输出
10的阶乘结果是: 3628800
1.6.7 enumerate del
1.enumerate
通过配合for遍历容器的同时获取元素的索引位置,元素本身
user_list = [{'name': 'tom', 'age': 19, 'height': 1.78}, {'name': 'jerry', 'age': 25, 'height': 1.56}, {'name': 'john', 'age': 17, 'height': 1.90}]
i = 0
for user_dict in user_list:
print(i, user_dict)
i += 1
print("正常情况下我们要遍历出一个嵌套字典的列表里的所有内容")
i = 0
print("=="*20)
for i, user_dict in enumerate(user_list):
print(i, user_dict)
上下俩段代码输出的内容是一致的
0 {'name': 'tom', 'age': 19, 'height': 1.78}
1 {'name': 'jerry', 'age': 25, 'height': 1.56}
2 {'name': 'john', 'age': 17, 'height': 1.9}
正常情况下我们要遍历出一个嵌套字典的列表里的所有内容
========================================
0 {'name': 'tom', 'age': 19, 'height': 1.78}
1 {'name': 'jerry', 'age': 25, 'height': 1.56}
2 {'name': 'john', 'age': 17, 'height': 1.9}
2. del
删除列表里指定的元素,使用方法有俩种。
del 列表[索引]
del(列表[索引])
del user_list[0]
print(user_list)
1.6.8 应用:学生名片管理系统(重要)
# 学生的列表应为全局变量,我们采用列表嵌套字典,用于保存用户信息
student_list = [{'name': 'Tom', 'age': 18, 'phone': '13824719558'}]
# 主界面应为一个死循环,因为必须一直停留在当前页面选择,以下为主界面逻辑
def main():
while True:
menu_print()
user_select = int(input("请输入需要选择的功能:"))
if user_select == 1:
print("添加学生信息")
add_student()
elif user_select == 2:
print("查询所有学生信息")
check_all_student()
elif user_select == 3:
print("查询指定学生信息")
check_student()
elif user_select == 4:
print("编辑指定学生信息")
edit_student()
elif user_select == 5:
print("删除指定学生信息")
delete_student()
elif user_select == 6:
print("退出学生名片管理系统")
break
else:
print("输入错误,请重新输入")
# 显示主界面菜单,菜单是每次选择选项并且完全选项内容后会重复出现的东西,那么我们可以给写成函数来重复调用
def menu_print():
print("=" * 10, "学生名片管理系统", "=" * 10)
print("1.添加学生信息")
print("2.查询所有学生信息")
print("3.查询指定学生信息")
print("4.修改指定学生信息")
print("5.删除指定学生信息")
print("6.退出系统")
print("=" * 40)
'''
开始做第一个选项的函数,先分清逻辑顺序
首先我们要输入3个内容,名字,年龄,电话
然后用for循环遍历查看里面有没有名字冲突的,如果有则添加失败并且提醒,用break跳出循环
如果没有则进入else添加用户字典到列表里
'''
def add_student():
new_name = input("请输入学生的名称:")
new_age = int(input("请输入学生的年龄:"))
new_phone = input("请输入学生的电话号码:")
for a, student_dict in enumerate(student_list):
if student_dict['name'] == new_name:
print("该学生已经存在系统,无需再次添加")
break
else:
new_student = {'name': new_name, 'age': new_age, 'phone': new_phone}
student_list.append(new_student)
print("添加学生信息成功")
'''
实现查询所有学生信息的功能
我们直接用之前学的enumerate直接遍历所有即可,如果为空则跳出循环
提示系统目前没有任何学生信息
'''
def check_all_student():
if not student_list:
print("系统目前没有任何学生信息,请先添加学生信息")
else:
print("序号\t\t姓名\t\t年龄\t\t电话")
for n, student_dict in enumerate(student_list):
print('%d\t\t%s\t\t%d\t\t%s' % (n+1, student_dict['name'], student_dict['age'], student_dict['phone']))
'''
实现查询指定学生的信息,
首先需要input来获取要查询学生的名字
然后遍历列表里的名字,如果没有则提示,有则显示内容
'''
def check_student():
check_name = input("请输入要查询的学生名字:")
for c, student_dict in enumerate(student_list):
if student_dict['name'] == check_name:
print("查到此学生")
print("学生信息如下\n")
print("序号\t\t姓名\t\t年龄\t\t电话")
print('%d\t\t%s\t\t%d\t\t%s' % (c + 1, student_dict['name'], student_dict['age'], student_dict['phone']))
break
else:
print("学生档案里无此学生的相关信息,请重新确认")
'''
同样的,我们要实现修改指定学生的档案,也是要经过一次筛选,但是不用Break跳过循环,
而是重新输入数据进行更改
'''
def edit_student():
check_name = input("请输入要修改的学生名字:")
for e, student_dict in enumerate(student_list):
if student_dict['name'] == check_name:
print("查到此学生")
print("学生信息如下\n")
print("序号\t\t姓名\t\t年龄\t\t电话")
print('%d\t\t%s\t\t%d\t\t%s' % (e + 1, student_dict['name'], student_dict['age'], student_dict['phone']))
edit_name = input("请输入要更改的学生名字:")
edit_age = int(input("请输入要更改的学生年龄:"))
edit_phone = input("请输入要更改的学生电话号码:")
student_list[e] = {'name': edit_name, 'age': edit_age, 'phone': edit_phone}
print("修改完成")
break
else:
print("学生档案里无此学生的相关信息,请重新确认")
'''
删除指定的学生档案同理
'''
def delete_student():
check_name = input("请输入要查询的学生名字:")
for d, student_dict in enumerate(student_list):
if student_dict['name'] == check_name:
print("查到此学生")
print("学生信息如下\n")
print("序号\t\t姓名\t\t年龄\t\t电话")
print('%d\t\t%s\t\t%d\t\t%s' % (d + 1, student_dict['name'], student_dict['age'], student_dict['phone']))
del student_list[d]
print("已删除该学生的信息")
break
else:
print("学生档案里无此学生的相关信息,请重新确认")
main()
# 字典输出问题,无法对齐提前打印的东西,格式化输出也不行,感觉需要一个表格才能限制,如果制表需要导入制表模块
下面是各项功能的测试
C:\Users\songs\AppData\Local\Programs\Python\Python38\python.exe "E:/Project/pythonProject/应用 学生管理系统.py"
========== 学生名片管理系统 ==========
1.添加学生信息
2.查询所有学生信息
3.查询指定学生信息
4.修改指定学生信息
5.删除指定学生信息
6.退出系统
========================================
请输入需要选择的功能:1
添加学生信息
请输入学生的名称:Kitty
请输入学生的年龄:17
请输入学生的电话号码:13455977884
添加学生信息成功
========== 学生名片管理系统 ==========
1.添加学生信息
2.查询所有学生信息
3.查询指定学生信息
4.修改指定学生信息
5.删除指定学生信息
6.退出系统
========================================
请输入需要选择的功能:2
查询所有学生信息
序号 姓名 年龄 电话
1 Tom 18 13824719558
2 Kitty 17 13455977884
========== 学生名片管理系统 ==========
1.添加学生信息
2.查询所有学生信息
3.查询指定学生信息
4.修改指定学生信息
5.删除指定学生信息
6.退出系统
========================================
请输入需要选择的功能:3
查询指定学生信息
请输入要查询的学生名字:larry
学生档案里无此学生的相关信息,请重新确认
学生档案里无此学生的相关信息,请重新确认
========== 学生名片管理系统 ==========
1.添加学生信息
2.查询所有学生信息
3.查询指定学生信息
4.修改指定学生信息
5.删除指定学生信息
6.退出系统
========================================
请输入需要选择的功能:3
查询指定学生信息
请输入要查询的学生名字:tom
学生档案里无此学生的相关信息,请重新确认
学生档案里无此学生的相关信息,请重新确认
========== 学生名片管理系统 ==========
1.添加学生信息
2.查询所有学生信息
3.查询指定学生信息
4.修改指定学生信息
5.删除指定学生信息
6.退出系统
========================================
请输入需要选择的功能:3
查询指定学生信息
请输入要查询的学生名字:Tom
查到此学生
学生信息如下
序号 姓名 年龄 电话
1 Tom 18 13824719558
========== 学生名片管理系统 ==========
1.添加学生信息
2.查询所有学生信息
3.查询指定学生信息
4.修改指定学生信息
5.删除指定学生信息
6.退出系统
========================================
请输入需要选择的功能:4
编辑指定学生信息
请输入要修改的学生名字:larry
学生档案里无此学生的相关信息,请重新确认
========== 学生名片管理系统 ==========
1.添加学生信息
2.查询所有学生信息
3.查询指定学生信息
4.修改指定学生信息
5.删除指定学生信息
6.退出系统
========================================
请输入需要选择的功能:4
编辑指定学生信息
请输入要修改的学生名字:Kitty
查到此学生
学生信息如下
序号 姓名 年龄 电话
2 Kitty 17 13455977884
请输入要更改的学生名字:Kitty
请输入要更改的学生年龄:19
请输入要更改的学生电话号码:13459844657
修改完成
========== 学生名片管理系统 ==========
1.添加学生信息
2.查询所有学生信息
3.查询指定学生信息
4.修改指定学生信息
5.删除指定学生信息
6.退出系统
========================================
请输入需要选择的功能:2
查询所有学生信息
序号 姓名 年龄 电话
1 Tom 18 13824719558
2 Kitty 19 13459844657
========== 学生名片管理系统 ==========
1.添加学生信息
2.查询所有学生信息
3.查询指定学生信息
4.修改指定学生信息
5.删除指定学生信息
6.退出系统
========================================
请输入需要选择的功能:5
删除指定学生信息
请输入要查询的学生名字:larry
学生档案里无此学生的相关信息,请重新确认
学生档案里无此学生的相关信息,请重新确认
========== 学生名片管理系统 ==========
1.添加学生信息
2.查询所有学生信息
3.查询指定学生信息
4.修改指定学生信息
5.删除指定学生信息
6.退出系统
========================================
请输入需要选择的功能:5
删除指定学生信息
请输入要查询的学生名字:Kitty
学生档案里无此学生的相关信息,请重新确认
查到此学生
学生信息如下
序号 姓名 年龄 电话
2 Kitty 19 13459844657
已删除该学生的信息
========== 学生名片管理系统 ==========
1.添加学生信息
2.查询所有学生信息
3.查询指定学生信息
4.修改指定学生信息
5.删除指定学生信息
6.退出系统
========================================
请输入需要选择的功能:2
查询所有学生信息
序号 姓名 年龄 电话
1 Tom 18 13824719558
========== 学生名片管理系统 ==========
1.添加学生信息
2.查询所有学生信息
3.查询指定学生信息
4.修改指定学生信息
5.删除指定学生信息
6.退出系统
========================================
请输入需要选择的功能:6
退出学生名片管理系统
Process finished with exit code 0
我们做一个功能之前一定要先理清楚,主次逻辑,主逻辑我们要实现什么功能,实现完成再去分次选项的实现,再把此选项的再重新做进去主功能里。