一、函数传参的四类参数
1、位置传参与关键字传参
# 位置传参,按照形参的位置顺序将实参的值传递给形参
# 关键字传参,指定实参给到哪个形参, 注意点: 关键字必须是函数的形参名
# 混合使用, 先写位置传参,再写关键字传参
'''先写没等号的,再写有等号的,有等号的要在后边'''
def func(a, b, c):
print(f'a:{a}')
print(f'b:{b}')
print(f'c:{c}')
# 位置传参
func(1,2,3)
# func(3,1,2)
# 关键字传参
func(a=10, b=20, c=30)
# func(c=10, a=20, b=30)
# 混合使用, 先写位置传参,再写关键字传参
'''先写没等号的,再写有等号的,有等号的要在后边'''
func(10, b=20, c=30)
# func(a=10, 20, 30) # 代码会报错
# func(10, a=30, b=20) # 代码会报错
2、缺省参数
"""
缺省参数,形参.在函数定义的时候,给形参一个默认值,这个形参就是缺省参数,
注意点: 缺省参数要写在普通参数的后边
特点: 在函数调用的时候,如果给缺省参数传递实参值,使用的是传递的实参值,如果没有传递,使用默认值
"""
# print()
'''
有等号的在后边写
'''
def func(a, b, c=10): # 形参c 称为缺省形参
print(f"a: {a}")
print(f"b: {b}")
print(f"c: {c}")
func(1, 2) # 没有给c 传递实参,使用默认值10
func(1, 2, 3) # 给c传递实参值,使用传递的数据3
# def fun1(a=1, b, c): # 代码报错,语法错误
# pass
3、不定长参数(重点)
有两个注意点: 函数定义中的 args 和 kwargs可以是任意的形参变量,不过习惯使用 args 和 kwargs.
'''
在形参前边加上一个*, 该形参变为不定长元组形参,可以接收所有的位置实参, 类型是元组(*args)
在形参前边加上两个**, 该形参变为不定长字典形参, 可以接收所有的关键字实参,类型是字典
(**kwargs)'''
# print(1)
# print(1, 2)
# print(1, 2, 3)
# print(1, 2, 3, 4)
# print(1, 2, 3, 4, 5)
def func(args, kwargs): # 两个普通的形参
print(args)
print(kwargs)
func(1, 2)
func(args=2, kwargs=1)
print('*' * 30)
print('*' * 30)
def func(*args, **kwargs):
print(args)
print(kwargs)
func(1, 2, 3, 3, 4, 5)
'''(1, 2, 3, 3, 4, 5)
{}'''
func(a=1, b=2, c=3, d=4)
'''()
{'a': 1, 'b': 2, 'c': 3, 'd': 4}'''
func(1, 2, 3, a=4, b=5, d=6)
'''(1, 2, 3)
{'a': 4, 'b': 5, 'd': 6}'''
重点!!!(下面的)
def func(*args, **kwargs):
print('args', args)
print('kwargs', kwargs)
my_list = [1, 2, 3, 4, 5, 6]
my_dict = {'a': 7, 'c': 8, 'b': 9, 'd': 10}
func(my_list) # 将列表作为一个数据进行传递(整体)
'''args ([1, 2, 3, 4, 5, 6],)
kwargs {}'''
func(*my_list) # 将列表中的每一个数据作为位置参数进行传递, 拆包
'''args (1, 2, 3, 4, 5, 6)
kwargs {}'''
# func(**my_list ) # 这个会报错,因为本来该是元组的类型,加两个*号,该放在字典的位置上,有冲突!
func(my_dict) # 将my_dict 作为一个位置实参进行传递(元组)
'''args ({'a': 7, 'c': 8, 'b': 9, 'd': 10},)
kwargs {}'''
func(*my_dict) # 将my_dict中的key 作为位置实参进行传递(元组)
'''args ('a', 'c', 'b', 'd')
kwargs {}'''
func(**my_dict) # 将my_dict中键值对作为关键字实参进行传递
'''args ()
kwargs {'a': 7, 'c': 8, 'b': 9, 'd': 10}'''
4、应用
def my_sum(*args, **kwargs):
num = 0
for i in args:
num += i # num = num + i
for j in kwargs.values():
num += j
print(f"求和的结果为{num}")
my_sum(1, 2, 3, a=4, b=5, c=6) # 21
5、函数参数的完整格式
#依次的顺序
普通形参 不定长元组形参 缺省形参 不定长字典形参
# 普通形参 缺省形参 不定长元组形参 不定长字典形参
def func(a, b=1): # 先普通再 缺省
pass
def func1(a, b=1, *args): # 语法上不会报错,但是缺省参数不能使用默认值
print('a', a)
print('b', b)
print(args)
def func2(a, *args, b=1): # 普通形参 不定长元组形参 缺省形参
print('a', a)
print('b', b)
print(args)
def func3(a, *args, b=1, **kwargs): # 普通形参 不定长元组形参 缺省形参 不定长字典形参
pass
# func1(1, 2, 3, 4)
# func2(1, 2, 3, 4)
func2(1, 2, 3, 4, b=10)
6、print函数中的sep
相当于是print函数默认的,自带空格属性,即缺省参数
# print(1)
# print(1, 2)
# print(1, 2, 3)
# print(1, 2, 3, 4)
# print(1, 2, 3, 4, 5)
print(1)
print(1, 2, sep='*')
print(1, 2, 3, sep='_*_') # 1_*_2_*_3
print(1, 2, 3, 4, sep='hello')
print(1,2) # 1 2
print(1, 2, 3, 4, 5, sep=' ') # 默认 1 2 3 4 5
二、拆包
1、组包与拆包
# 组包,将多个数据值,组成元组,给到一个变量
# 拆包:将容器的数据分别给到多个变量,需要注意:数据的个数和变量的个数要保持一致
# 组包,将多个数据值,组成元组,给到一个变量
a = 1, 2, 3
print(a) # (1, 2, 3)
def func():
return 1, 2 # 组包
# 拆包:将容器的数据分别给到多个变量,需要注意:数据的个数和变量的个数要保持一致
b, c, d = a # 拆包 把a的值分别给了b,c,d
print(b,c,d)
e,f = func()
print(e,f) # 1 2
my_list = [10,20]
a,b = my_list
print(a, b) # 10 20
my_dict = {'name': 'isaac', 'age': 18}
a, b = my_dict # key值
print(a, b) # name age
2、应用
可以在冒泡排序中使用!
直接交换两数的值,不需要第三个临时变量来辅助,本质上是拆包
a = 10
b = 20
# 方法一:
# c = a
# a = b
# b = c
# print(a, b)
# 方法二: +/- */÷
# a = a + b # a 30
# b = a - b # 10
# a = a - b # 20
'''后面的两次虽然书写上是一样的,但是意义不同'''
# print(a, b)
# 方法三, python中的使用 组包和拆包
a, b = b, a
print(a, b)
三、引用
1、变量的引用
本质上就是地址,
Python意思是数字都有地址,而变量是将自己的地址指向了数字(即将数字的地址保存在变量中)
# 可以使用 id() 查看变量的引用, 可以将id 值认为是内存地址的别名
# python中数据值的传递的是引用
# 赋值运算符可以改变变量的引用
# 将数据10 存储到变量a 中, 本质是将数据10 所在内存的引用地址保存到变量a 中
a = 10
# 将变量a中保存的引用地址给给到b
b = a
print(a, b) # 使用print函数打印变量a 和 b 引用中存储的值
print(id(a), id(b))
a = 20
print(a, b)
print(id(a), id(b))
2、列表的引用
my_list = [1, 2, 3] # 将列表的引用地址保存到变量my_list 中
my_list1 = my_list # 将my_list 变量中存储的引用地址给到 my_list1
print(my_list, id(my_list))
print(my_list1, id(my_list1))
my_list.append(4) # 向列表中添加数据4, 将数据4 的引用保存到列表中
print(my_list, id(my_list))
print(my_list1, id(my_list1))
my_list[2] = 5
print(my_list, id(my_list))
print(my_list1, id(my_list1))
'''
列表的地址引用没有发生变化,属于可变类型(可以添加数据)
'''
3、类型的可变与不可变
# 类型的可变与不可变: 在不改变变量引用的前提下,能否改变变量中引用中的数据,
# 如果能改变是可变类型, 如果不能改变,是不可变类型
# int float bool str list tuple dict
# 不可变类型: int float bool str tuple
# 可变类型: list dict
# num = 10
# num = 20
#
# my_list = [1, 2]
# my_list.append(3)
a = 1000
b = 1000
print(id(a), id(b)) # python中的内存优化,对于不可变类型进行的,
print(id(a) == id(b))
a = 'hello'
b = 'hello'
print(id(a), id(b)) # python中的内存优化,对于不可变类型进行的,
my_tuple = (1, 2)
my_tuple1 = (1, 2)
print(id(my_tuple), id(my_tuple1))
print(id(my_tuple) == id(my_tuple1))
print('-' * 20)
my_list = [1, 2, 3]
my_list1 = [1, 2, 3]
print(id(my_list), id(my_list1))
print('*' * 30)
my_tuple2 = (1, 2, [3, 4])
print(my_tuple2)
my_tuple2[2][1] = 10
print(my_tuple2)
4、引用作为函数参数传递
关系到到底要不要在函数中添加global
# 函数传参传递的也是引用
my_list = [1, 2, 3] # 全局变量
def func1(a):
a.append(4)
def func2():
# 为啥不加global, 因为没有修改 my_list 中存的引用值
my_list.append(5)
def func3():
global my_list
my_list = [1, 2, 3] # 修改全局变量的值
def func4(a):
# += 对于列表来说,类似列表的extend方法,不会改变变量的引用地址
a += a # a = a + a, 修改了a变量a的引用
# print(a)
func1(my_list) # [1, 2, 3, 4]
func2() # [1, 2, 3, 4, 5]
func3() # [1, 2, 3]
print(my_list)
b = 10 # 不可变类型
func4(b)
print(b) #
func4(my_list)
print(my_list) # [1, 2, 3, 1, 2, 3]
四、学生管理系统(初步)(两种办法)
方法一
# 定义学生列表,保存所有的学生信息
stu_list = []
def show_menu():
print('1. 添加学生')
print('2. 删除学生')
print('3. 修改学生信息')
print('4. 查询单个学生信息')
print('5. 查询所有的学生信息')
print('6. 退出系统')
def insert_student():
# 1. 通过 input 函数获取学生的信息, 姓名, 年龄, 性别
name = input('请输入学生名字:')
# [{}, {}, {}] 判断的是字典中的 value 是否存在
for stu in stu_list:
if stu['name'] == name:
print('----------学生信息存在---------')
return # 结束函数的执行
age = input('请输入学生年龄:')
gender = input('请输入学生性别:')
# 2. 将学生信息转换为字典进行保存
stu_dict = {'name': name, 'age': int(age), 'gender': gender}
# 3. 将这个学生字典添加的列表中
stu_list.append(stu_dict)
print('==============学生信息添加成功====================')
def remove_student():
# 1. 使用 input 获取要删除 /修改/查询 的学生姓名
name = input('请输入要操作的学生的名字:')
# 2. 判断学生信息是否存在
for stu in stu_list:
if stu['name'] == name:
# 3. 学生存在,对学生进行 删除 /修改/查询 操作
stu_list.remove(stu)
# return
break
# 4. 学生信息不存在,直接结束
else:
print('***********该学生信息不存在,无法删除**************')
def modify_student():
# 1. 使用 input 获取要删除 /修改/查询 的学生姓名
name = input('请输入要操作的学生的名字:')
# 2. 判断学生信息是否存在
for stu in stu_list:
if stu['name'] == name:
# 3. 学生存在,对学生进行 删除 /修改/查询 操作
stu['age'] = int(input('请输入新的年龄:'))
# return
break
# 4. 学生信息不存在,直接结束
else:
print('***********该学生信息不存在,无法修改**************')
def search_student():
# 1. 使用 input 获取要删除 /修改/查询 的学生姓名
name = input('请输入要操作的学生的名字:')
# 2. 判断学生信息是否存在
for stu in stu_list:
if stu['name'] == name:
# 3. 学生存在,对学生进行 删除 /修改/查询 操作
print(f'姓名:{stu["name"]}, 年龄:{stu["age"]}, 性别:{stu["gender"]}')
# return
break
# 4. 学生信息不存在,直接结束
else:
print('***********该学生信息不存在**************')
def show_all_info():
if len(stu_list) > 0:
for stu in stu_list:
print(f'姓名:{stu["name"]}, 年龄:{stu["age"]}, 性别:{stu["gender"]}')
# print(stu)
else:
print('目前没有学生信息')
def main():
while True:
show_menu()
opt = input('请输入用来选择的操作编号:')
if opt == '1':
# print('1. 添加学生')
insert_student()
elif opt == '2':
# print('2. 删除学生')
remove_student()
elif opt == '3':
# print('3. 修改学生信息')
modify_student()
elif opt == '4':
# print('4. 查询单个学生信息')
search_student()
elif opt == '5':
# print('5. 查询所有的学生信息')
show_all_info()
elif opt == '6':
print('欢迎下次使用本系统......')
break
else:
print('输入有误,请再次输入')
continue
input('...... 回车键继续操作.......')
main()
方法二、
student = []
def main():
while True:
show()
i = input("请输入操作编号:")
if i == '1':
insert() # 添加
elif i == '2':
remove() # 删除
elif i == '3':
modify() # 修改
elif i == '4':
search() # 查询
elif i == '5':
showAll() # 查询所有信息
elif i == '6':
print("==========欢迎下次使用本系统==========")
else:
print("==========输入有误,请再次输入!==========")
continue
input("==========按回车键继续==========")
def show():
print('1. 添加学生')
print('2. 删除学生')
print('3. 修改学生信息')
print('4. 查询单个学生信息')
print('5. 查询所有的学生信息')
print('6. 退出系统')
def insert():
"""
添加学生信息
"""
name = input("请输入学生的姓名:")
for s in student:
if s['name'] == name:
print("该学生信息已存在,请再次输入指令!")
return
age = input("请输入学生的年龄:")
sex = input("请输入学生的性别:")
stu_dict = {'name': name, 'age': age, 'sex': sex}
student.append(stu_dict)
print('==========学生信息添加完成==========')
def remove():
name = input('请输入要删除的学生的姓名:')
for stu in student:
if stu['name'] == name:
# 3. 学生存在,对学生进行 删除 /修改/查询 操作
student.remove(stu)
# return
break
else:
print('==========该学生信息不存在,无法删除==========')
def modify():
# 1. 使用 input 获取要删除 /修改/查询 的学生姓名
name = input('请输入要操作的学生的名字:')
# 2. 判断学生信息是否存在
for stu in student:
if stu['name'] == name:
# 3. 学生存在,对学生进行 删除 /修改/查询 操作
stu['age'] = int(input('请输入新的年龄:'))
# return
break
# 4. 学生信息不存在,直接结束
else:
print('==========该学生信息不存在,无法修改==========')
def search():
# 1. 使用 input 获取要删除 /修改/查询 的学生姓名
name = input('请输入要操作的学生的名字:')
# 2. 判断学生信息是否存在
for stu in student:
if stu['name'] == name:
# 3. 学生存在,对学生进行 删除 /修改/查询 操作
print(f'姓名:{stu["name"]}, 年龄:{stu["age"]}, 性别:{stu["gender"]}')
# return
break
# 4. 学生信息不存在,直接结束
else:
print('==========该学生信息不存在==========')
def showAll():
if len(student) > 0:
for stu in student:
print(f'姓名:{stu["name"]}, 年龄:{stu["age"]}, 性别:{stu["gender"]}')
# print(student)
else:
print('目前没有学生信息')
main()
五、练习
1、
"""
如下所示这是一个字典,{"name":"电脑","price":7000}
请定义这样一个函数num,讲上述字典中的键值对传入到函数num中,要求用不定长参数来接收,并在函数中打印键值对输出
输出格式为:
key: name value: 电脑
key: price value: 700
"""
def num(**kwargs):
for key, value in kwargs.items():
print("key:", key, "value:", value)
num(name="电脑", price=700)
2、
"""
对于一个函数num,当调用nun(1,2,a=3,b=4)和调用num(3,4,5,6,a=1)以及num(a=1,b=2)的时候都可以正常运行,并且可以对元组以及字典类型进行遍历输出,对字典类型进行输出字典的键值对(形式为:key:a,value:1),
请写出这个函数并完成调用。
"""
def num(*args, **kwargs):
for i in args:
print(i)
for key, value in kwargs.items():
print("key:", key, "value:", value)
num(1, 2, 3, a=1, b=2)
# num(a=1, b=2) 此种情况也可