函数
目录
函数
一、容器知识补充
1、字典遍历方法
2、遍历字典元素
keys()方法:
values()方法:
items()方法:
3、公共运算符
4、公共方法
二、函数介绍
1、函数的概念
2、引入函数
3、函数定义与调用
4、函数的参数
5、函数的返回值
6、说明文档
三、函数的嵌套调用
1、嵌套调用及执行流程
2、嵌套调用的应用
四、变量的作用域
1、局部变量
2、全局变量
五、函数的多种参数
1、位置参数
2、关键字参数
3、缺省参数
4、不定长参数
六、拆包和交换变量值
1、拆包
2、交换变量值
七、引用
1、了解引用
2、把引用当做参数传递
八、匿名函数
1、lambda语法
2、lambda的应用
一、容器知识补充
1、字典遍历方法
当要遍历字典的元素内容,即获取字典的键、值。
常用方法:
函数名 | 含义 |
---|---|
keys() | 以列表的形式,返回一个字典所有的键。 |
values() | 以列表的形式,返回一个字典所有的值。 |
items() | 返回由键值组成的序列,主要应用于遍历字典。 |
为便于理解几个方法,可简要理解为:
2、遍历字典元素
keys()方法:
函数名 | 含义 |
---|---|
keys() | 以列表的形式,返回一个字典所有的键。 |
在Python中,字典(dictionary)的keys()
函数返回的是一个字典视图对象(dictionary view object),具体来说是“字典键视图”(dictionary keys view)。
这个视图对象是一个动态集合,它展示了字典的键。这个视图对象支持集合操作,如迭代、成员检查等,但它不是列表或元组。
说明:
获取所有键内容,可以当做列表进行处理。
values()方法:
函数名 | 含义 |
---|---|
values() | 以列表的形式,返回一个字典所有的值。 |
说明:
获取所有值,可以当做列表处理。
items()方法:
函数名 | 含义 |
---|---|
items() | 返回由键值组成的序列,主要应用于遍历字典。 |
说明 :
获取所有的键值。
例如,一起来完成:
(1)定义一个字典变量,存放一个学生的信息:姓名、住址、年龄等;
(2)获取字典变量中的所有键,并输出【键 --> 值】形式结果;
(3)获取字典变量中的所有值并输出;
(4)获取字典变量中的所有键、值序列;
(5)执行程序,观察效果。
datas = {"name": "张三丰",
"address": "武当山",
"age": 147}
print('--------1、获取所有的键----------------')
# keys()获取所有的键,得到一个字典视图对象
print(datas.keys()) # 获取的是一个对象,内部包含列表:dict_keys(['name', 'address', 'age'])
print(list(datas.keys())) # 得到列表: ['name', 'address', 'age']
print('--------2、遍历-方式1----------------')
# 遍历-方式1
for key in datas.keys(): #遍历时,不需要将keys()获取的内容进行列表转换,直接遍历即可
print(key+'------'+str(datas.get(key)))
print('--------4、获取所有的键值对项----------------')
print(datas.items()) #dict_items([('name', '张三丰'), ('address', '武当山'), ('age', 147)])
print('--------3、遍历-方式2----------------')
for kv in datas.items(): # kv就是一个元组: ('name', '张三丰')
print(kv[0]+'-----------'+str(kv[1]))
print('--------4、获取所有的值----------------')
#values() 得到一个字典视图对象
print(datas.values()) # dict_values(['张三丰', '武当山', 147])
print(list(datas.values())) # ['张三丰', '武当山', 147]
3、公共运算符
公共运算符指的是:可以运用于Python容器的一下运算符。
常见公共运算符:
运算符 | 描述 | 支持的容器类型 |
---|---|---|
+ | 合并 | 字符串、列表、元组 |
* | 复制 | 字符串、列表、元组 |
in | 元素是否存在 | 字符串、列表、元组、字典 |
not in | 元素是否不存在 | 字符串、列表、元组、字典 |
例如,一起来完成:
(1)定义字符串变量,并完成+、*的运算操作;
(2)定义列表变量,并完成in、not in的运算操作。
print('---------运算符:+-----------------')
# ------字符串-----
str1 = 'hello'
str2 = 'world'
num = 123
print(str1 + str2) # +两端只能跟字符串
print(str1 + str(num)) # +两端只能跟字符串,否则需要进行类型强转
# -----列表-----
list1 = [1,2,3]
list2 = [3,4,5,6]
list3 = list1 + list2
print(list1) # list1不变
print(list2) # list2不变
print(list3) # list3为list1和list2合并后的结果
# 以下方式也可以将list1和list2进行合并
list1.extend(list2)
print(list1)
# -----元组-----
tuple1 = (1,2,3)
tuple2 = (3,4,5,6)
tuple3 = tuple1 + tuple2
print(tuple1)
print(tuple2)
print(tuple3) # tuple3为tuple1和tuple2合并后的结果
print('---------运算符:* -----------------')
str1 = 'itcast'
print(str1 * 10) # 让str1重复10次
list1 = [1,2,3]
print(list1 * 10) # 列表的内容被复制10倍
tuple1 = (1,2,3)
print(tuple1 * 10)
print('---------运算符: in和not in -----------------')
# -----字符串
str1 = 'I love itcast'
if 'v' in str1:
print('字符v在字符串中')
else:
print('字符v不在字符串中')
# -----列表
list1 = ['刘备','关羽','张飞']
if '关羽' in list1:
print('关羽在列表中')
else:
print('关羽不在列表中')
# -----字典
dict1 = {'name':'刘备','age':18}
if 'age' not in dict1:
print('age这个键在字典中')
else:
print('age这个键不在字典中')
4、公共方法
公共方法指的是:能适用于Python容器的一些通用方法。
常见公共方法:
描述 | |
---|---|
len(s) | 计算容器中的元素总个数 |
del | 删除 |
max() | 返回容器中元素最大值 |
min() | 返回容器中元素最小值 |
例如,一起来完成:
(1)定义一个列表变量,内容为:10、300、20、200、30、100、0;
(2)获取列表变量的总长度;
(3)获取列表的最大值和最小值;
(4)思考:为何有些方法可直接使用,比如:max()、len(),而大多数方法都需要使用【变量名.函数(xx)】形式调用?
# 1.定义变量
list1 = [10,300,20,200,30,100,0]
# 2.长度
print(len(list1))
# 3.最大最小值
print(max(list1))
print(min(list1))
# 4.删除元素
del list1[1]
print(list1)
# 5、查看Python所有的内置函数
print(dir(__builtins__))
注意:当要查看Python内置[函数]有哪些时,可以使用dir(__builtins__)来查看。
二、函数介绍
1、函数的概念
在Python函数中,有几个重要概念:
(1)函数名
(2)参数
(3)返回值
为了更好的理解函数的几个概念。通过【我给钱让儿子帮我买包烟】为例说明。
整个过程:我给钱给我儿子,然后儿子帮我去买烟,最后他成功把烟拿给了我。
比如,买烟可以比作为一个函数名,那么给的钱就看作是参数,最终儿子拿给我的烟可以比作是返回值。
买烟(钱):
...[买烟过程]
返回: 烟
函数语法:
def 函数名(参数, ..):
代码1
代码2
...
[return 具体的值]
总结:
(1)当将一些代码进行封装在一块,并给这块代码取了个名字,就叫做函数;
(2)定义函数时,需要使用def关键字。
2、引入函数
据说,项目开发前运行【佛祖镇楼】案例,可以减少项目Bug,一起看看。
比如,某个程序在不同的条件下,要输出【佛祖镇楼】,那么,程序可以使用if语句判断处理:
if 条件1:
输出"佛祖镇楼"
……
elif 条件2:
输出"佛祖镇楼"
……
elif 条件3:
输出"佛祖镇楼"
……
……(省略)
仔细观察,我们会发现:需要输出多次的【佛祖镇楼】。
此时,就可以使用函数解决重复编写代码的问题。
例如,一起来完成:
(1)当从键盘上输入数值1-6之间的某个自然数时,则输出【佛祖镇楼】;
(2)使用函数形式改进程序;
(3)对比两个程序代码并执行,观察效果。
# # 1.定义变量
# number = int(input("请输入数字:"))
# # 2.判断
# if number == 1:
# # 3.输出
# print(" _ooOoo_ ")
# print(" o8888888o ")
# print(" 88 . 88 ")
# print(" (| -_- |) ")
# print(" O\\ = /O ")
# print(" ____/`---'\\____ ")
# print(" . ' \\| |// `. ")
# print(" / \\||| : |||// \\ ")
# print(" / _||||| -:- |||||_ \ ")
# print(" | | \\\\\\ - /// | | ")
# print(" | \\_| ''\\---/'' | | ")
# print(" \\ ..\__ `-` ___/-. / ")
# print(" ___`. .' /--.-.\ `. . __ ")
# print(" ."" '< `.___\\_<|>_/___.' >'"". ")
# print(" | | : `- \\`.;`\\ _ /`;.`/ - ` : | | ")
# print(" \\ \\ `-. \\_ __\\ /__ _/ .-` / / ")
# print(" ======`-.____`-.___\\_____/___.-`____.-'====== ")
# print(" `=---=' ")
# print(" ")
# print(" ............................................. ")
# print(" .........佛祖镇楼...................bug辟易...")
# print(" 佛曰: ")
# print(" 写字楼里写字间,写字间里程序员; ")
# print(" 程序人员写程序,又拿程序换酒钱。 ")
# print(" 酒醒只在网上坐,酒醉还来网下眠; ")
# print(" 酒醉酒醒日复日,网上网下年复年。 ")
# print(" 但愿老死电脑间,不愿鞠躬老板前; ")
# print(" 奔驰宝马贵者趣,公交自行程序员。 ")
# print(" 别人笑我太疯癫,我笑自己命太贱; ")
# print(" 不见满街漂亮妹,哪个归得程序员?")
# elif number == 2:
# print(" _ooOoo_ ")
# print(" o8888888o ")
# print(" 88 . 88 ")
# print(" (| -_- |) ")
# print(" O\\ = /O ")
# print(" ____/`---'\\____ ")
# print(" . ' \\| |// `. ")
# print(" / \\||| : |||// \\ ")
# print(" / _||||| -:- |||||_ \ ")
# print(" | | \\\\\\ - /// | | ")
# print(" | \\_| ''\\---/'' | | ")
# print(" \\ ..\__ `-` ___/-. / ")
# print(" ___`. .' /--.-.\ `. . __ ")
# print(" ."" '< `.___\\_<|>_/___.' >'"". ")
# print(" | | : `- \\`.;`\\ _ /`;.`/ - ` : | | ")
# print(" \\ \\ `-. \\_ __\\ /__ _/ .-` / / ")
# print(" ======`-.____`-.___\\_____/___.-`____.-'====== ")
# print(" `=---=' ")
# print(" ")
# print(" ............................................. ")
# print(" .........佛祖镇楼...................bug辟易...")
# print(" 佛曰: ")
# print(" 写字楼里写字间,写字间里程序员; ")
# print(" 程序人员写程序,又拿程序换酒钱。 ")
# print(" 酒醒只在网上坐,酒醉还来网下眠; ")
# print(" 酒醉酒醒日复日,网上网下年复年。 ")
# print(" 但愿老死电脑间,不愿鞠躬老板前; ")
# print(" 奔驰宝马贵者趣,公交自行程序员。 ")
# print(" 别人笑我太疯癫,我笑自己命太贱; ")
# print(" 不见满街漂亮妹,哪个归得程序员?")
# elif number == 3:
# print(" _ooOoo_ ")
# print(" o8888888o ")
# print(" 88 . 88 ")
# print(" (| -_- |) ")
# print(" O\\ = /O ")
# print(" ____/`---'\\____ ")
# print(" . ' \\| |// `. ")
# print(" / \\||| : |||// \\ ")
# print(" / _||||| -:- |||||_ \ ")
# print(" | | \\\\\\ - /// | | ")
# print(" | \\_| ''\\---/'' | | ")
# print(" \\ ..\__ `-` ___/-. / ")
# print(" ___`. .' /--.-.\ `. . __ ")
# print(" ."" '< `.___\\_<|>_/___.' >'"". ")
# print(" | | : `- \\`.;`\\ _ /`;.`/ - ` : | | ")
# print(" \\ \\ `-. \\_ __\\ /__ _/ .-` / / ")
# print(" ======`-.____`-.___\\_____/___.-`____.-'====== ")
# print(" `=---=' ")
# print(" ")
# print(" ............................................. ")
# print(" .........佛祖镇楼...................bug辟易...")
# print(" 佛曰: ")
# print(" 写字楼里写字间,写字间里程序员; ")
# print(" 程序人员写程序,又拿程序换酒钱。 ")
# print(" 酒醒只在网上坐,酒醉还来网下眠; ")
# print(" 酒醉酒醒日复日,网上网下年复年。 ")
# print(" 但愿老死电脑间,不愿鞠躬老板前; ")
# print(" 奔驰宝马贵者趣,公交自行程序员。 ")
# print(" 别人笑我太疯癫,我笑自己命太贱; ")
# print(" 不见满街漂亮妹,哪个归得程序员?")
# elif number == 4:
# print(" _ooOoo_ ")
# print(" o8888888o ")
# print(" 88 . 88 ")
# print(" (| -_- |) ")
# print(" O\\ = /O ")
# print(" ____/`---'\\____ ")
# print(" . ' \\| |// `. ")
# print(" / \\||| : |||// \\ ")
# print(" / _||||| -:- |||||_ \ ")
# print(" | | \\\\\\ - /// | | ")
# print(" | \\_| ''\\---/'' | | ")
# print(" \\ ..\__ `-` ___/-. / ")
# print(" ___`. .' /--.-.\ `. . __ ")
# print(" ."" '< `.___\\_<|>_/___.' >'"". ")
# print(" | | : `- \\`.;`\\ _ /`;.`/ - ` : | | ")
# print(" \\ \\ `-. \\_ __\\ /__ _/ .-` / / ")
# print(" ======`-.____`-.___\\/___.-`____.-'====== ")
# print(" `=---=' ")
# print(" ")
# print(" ............................................. ")
# print(" .........佛祖镇楼...................bug辟易...")
# print(" 佛曰: ")
# print(" 写字楼里写字间,写字间里程序员; ")
# print(" 程序人员写程序,又拿程序换酒钱。 ")
# print(" 酒醒只在网上坐,酒醉还来网下眠; ")
# print(" 酒醉酒醒日复日,网上网下年复年。 ")
# print(" 但愿老死电脑间,不愿鞠躬老板前; ")
# print(" 奔驰宝马贵者趣,公交自行程序员。 ")
# print(" 别人笑我太疯癫,我笑自己命太贱; ")
# print(" 不见满街漂亮妹,哪个归得程序员?")
# 代码很多重复? -->不好维护
def show_no_bug():
# 3.输出
print(" _ooOoo_ ")
print(" o8888888o ")
print(" 88 . 88 ")
print(" (| -_- |) ")
print(" O\\ = /O ")
print(" ____/`---'\\____ ")
print(" . ' \\| |// `. ")
print(" / \\||| : |||// \\ ")
print(" / _||||| -:- |||||_ \ ")
print(" | | \\\\\\ - /// | | ")
print(" | \\_| ''\\---/'' | | ")
print(" \\ ..\__ `-` ___/-. / ")
print(" ___`. .' /--.-.\ `. . __ ")
print(" ."" '< `.___\\_<|>_/___.' >'"". ")
print(" | | : `- \\`.;`\\ _ /`;.`/ - ` : | | ")
print(" \\ \\ `-. \\_ __\\ /__ _/ .-` / / ")
print(" ======`-.____`-.___\\_____/___.-`____.-'====== ")
print(" `=---=' ")
print(" ")
print(" ............................................. ")
print(" .........佛祖镇楼...................bug辟易...")
print(" 佛曰: ")
print(" 写字楼里写字间,写字间里程序员; ")
print(" 程序人员写程序,又拿程序换酒钱。 ")
print(" 酒醒只在网上坐,酒醉还来网下眠; ")
print(" 酒醉酒醒日复日,网上网下年复年。 ")
print(" 但愿老死电脑间,不愿鞠躬老板前; ")
print(" 奔驰宝马贵者趣,公交自行程序员。 ")
print(" 别人笑我太疯癫,我笑自己命太贱; ")
print(" 不见满街漂亮妹,哪个归得程序员?")
# 1.定义变量
number = int(input("请输入数字:"))
# 2.判断
if number == 1:
show_no_bug()
elif number == 2:
show_no_bug()
elif number == 3:
show_no_bug()
elif number == 4:
show_no_bug()
# 解决了代码重复问题;
# 提升了代码阅读能力
总结:
(1)当要减少代码的重复和代码冗余时,就可以使用Python函数;
(2)请问:使用函数可以提升代码的阅读性,这句话正确吗?
3、函数定义与调用
Python函数需要使用def关键字来定义。使用方式有两步:
(1)先定义
(2)后调用
当然了,函数在使用时,特点:
(1)先定义,后调用;
(2)不调用,不执行;
(3)调用一次,执行一次。
接着,来一起看看函数的语法。
定义函数:
def 函数名():
代码1
代码2 ...
调用函数:
函数名()
例如,一起来完成:
(1)编写一个show()函数,并在函数中输出:bug虐我千百遍, 我待bug如初恋。
(2)调用函数,观察执行结果。
4、函数的参数
当在定义函数时,设定了参数,则可称该函数为:有参函数。反之,没有参数的函数,称为:无参函数。
定义有参数的函数,语法:
def 函数名(参数1,参数2,...): # 形参
代码1
代码2
...
调用函数,语法:
函数名(参数值1,参数值2,...) # 实参
说明:
(1)形参是指形式参数,表示在定义函数时的参数;
(2)实参是指实际参数,表示在调用函数时传递的参数值,具有实际意义。
例如,一起来完成:
(1)定义一个函数,用于求解两个数之和;
(2)接着,调用函数并执行程序,观察效果。
# 1.定义函数
def get_sum(a,b):
ret = a + b
print(f"两个数之和为:{ret}")
# 2.调用函数
get_sum(10,20)
# get_sum(90) # 报错
总结:
(1)当定义了有参数的函数时,调用函数也需要传递参数值;
(2)注意:当给有参函数传递参数时,要关注参数的三要素:个数、类型、顺序。
5、函数的返回值
函数的返回值指的是:当函数完成一件事情后,最后要返回给函数的结果。
返回值语法:
def 函数名([参数1, 参数2, ...]):
代码1
代码2
...
return 值
说明:
(1)若要给函数返回结果,需要使用return关键字;
(2)return关键字的作用:把结果返回给函数;结束函数;
(3)当函数没有返回值时,默认返回None。
print('-----------无参,无返回值-------------')
# 1、定义函数-无参,无返回值
def show():
print('这是一个函数,无参,无返回值')
# 2、调用函数
show()
show()
print('-----------有参,有返回值-------------')
# 1、定义函数:有参,有返回值 --->求两个数的和
# 该函数没有限定参数类型,理论上可以传入任何类型,但是可能会报错
def get_sum(num1, num2): # 形参
return num1 + num2
# 该函数限定参数类型必须是int,返回值也是int,一般封装系统级函数时,可以使用
def get_sum2(num1: int, num2: int) -> int: # 形参
return num1 + num2
# 2、调用函数
# 方式1
result1 = get_sum(10, 20) # 实参
print(result1)
# 方式2
print(get_sum(10, 20)) # 实参
print(get_sum('hello', 'world'))
# print(get_sum2('hello', 'world')) # 报错,类型不一致
print('-----------有参, 无返回值-------------')
# 如果一个函数没有指定返回值,默认会在函数尾部加:return None
# 1、定义函数
def func1(num):
for i in range(num):
print('********************')
# 2、调用函数
func1(5)
print('-----------无参, 有返回值-------------')
# 1、定义函数
import random
def get_random_number_between_1_and_100():
return random.randint(1, 100)
# 2、调用函数
print(get_random_number_between_1_and_100())
总结:
(1)当函数没有返回值时,在函数内部代码最后一行会有默认代码:return None
(2)注意:return关键字的作用有两个:(一)把结果返回给函数;(二)结束函数。
-
函数返回多个值
# 需求:定义一个函数,传入一个数字列表,返回列表的最大值,最小值,平均值 # 1、定义函数 def get_list_result(list_name): max_value = max(list_name) min_value = min(list_name) avg_value = sum(list_name) / len(list_name) return max_value, min_value, avg_value # 返回的时元组 # 2、调用函数 list1 = [1, 2, 3, 4, 5, 30, 50] result = get_list_result(list1) print(type(result)) # <class 'tuple'> print(f'最大值:{result[0]}') # 使用索引来访问元组中的元素 print(f'最小值:{result[1]}') # 使用索引来访问元组中的元素 print(f'平均值:{result[2]}') # 使用索引来访问元组中的元素
6、说明文档
说明文档指的是:在定义函数的第一行,加上多行注释。这样的操作,可以让函数更加规范化。
当添加了说明文档后,在调用函数时,就能查看到函数的作用提示。
说明:
查看下print()函数。
接着,一起来看看在自定义函数时,如何给函数添加说明文档?
添加说明文档的语法:
def 函数名():
""" 说明文档的位置 """
代码
...
当需要看函数的说明文档的具体内容时,语法:
help(函数名)
# 1、定义函数时,给函数加说明书
def get_list_result(list_name):
"""
这是一个获取列表信息的函数
:param 列表名
:return: 最大值、最小值、平均值
"""
max_value = max(list_name)
min_value = min(list_name)
avg_value = sum(list_name) / len(list_name)
return max_value, min_value, avg_value # 返回的时元组
# 使用方式1:调用函数时,将光标放在函数名字上,就会有说明信息
get_list_result()
# 使用方式2:调用help函数,打印函数说明书
help(get_list_result)
总结:
(1)为了更规范的给函数添加注释,通常会在定义函数的第1行做解释说明
(2)通俗地说,说明文档就是更规范地给函数添加多行注释,注释只能通过源码来查看,而文档说明可以在任何位置查看
三、函数的嵌套调用
1、嵌套调用及执行流程
函数的嵌套调用指的是:在一个函数中,调用了另一个函数。
嵌套调用语法:
def 函数1():
代码
...
def 函数2():
代码
# 调用函数1
函数1()
...
说明:
在函数2中,调用了函数1。
例如,一起来完成:
(1)先定义一个test()函数和func()函数;
(2)接着,在函数test()中,嵌套调用func()函数,并在外部调用test()函数;
(3)执行程序,观察效果;
(4)思考:嵌套调用的执行流程是怎样的呢?
# 1.定义func()
def func():
print("==========AA===============")
print("==========Nfunc()============")
print("==========BB===============")
# 2.定义test()、调用func()
def test():
print("*************11****************")
func()
print("**********M调用了test方法**************")
print("*************22****************")
# 3.调用test()
test() # 1ANBM2
# 说明流程
# 定义函数test1()
def test1():
print('这个是test1函数')
# 嵌套调用
def test2():
test1()
print('这个是test2函数')
# 调用函数test2
test2()
print('------------------------------------------')
def 数据采集():
print('数据采集中!')
def 数据预处理():
print('数据预处理中!')
def 数据分析():
print('数据分析中!')
def 数据导出():
print('数据导出中!')
def shufen():
数据采集()
数据预处理()
数据分析()
数据导出()
# 调用函数
shufen()
总结:
(1)嵌套调用指的是:一个函数中,调用了另一个函数;
(2)注意:函数的嵌套调用执行流程较为复杂,需要多观察执行结果。
2、嵌套调用的应用
使用函数的嵌套调用,我们可以把复杂问题分解成多个简单问题,这样便于解决问题。
比如,要求多个数的平均值。此时,我们就可以拆分为两个函数:
(a)函数A:用于求解多个数之和;
(b)函数B:调用函数A,获取多个数之和,接着,再使用和除以总个数,就能求解出平均值。
例如,一起来完成:
(1)要完成一个输出任意条横线的需求;
(2)定义函数1:用于输出一条横线;
(3)定义函数2:先循环N次,再调用函数1,可输出N条横线;
(4)执行程序,观察效果。
# 1.定义一条横线的函数
def print_one_line():
print("-"*40)
# 2.N条横线
def print_lines(n):
for i in range(n):
print_one_line()
print_lines(10)
总结:采用函数的嵌套调用,可以让复杂问题简单化。
四、变量的作用域
1、局部变量
先来了解一下作用域的概念!
作用域指的是:内容生效的具体范围。
当根据作用域的不同,可以给变量分为两类:
(1)局部变量
(2)全局变量
局部变量指的是:定义在函数内部的变量或参数,且只在函数中生效。
局部变量语法:
def 函数名(参数1,参数2,...):
代码
变量名 = 值
...
说明:局部变量只作用在函数中。
例如,一起来完成:
(1)定义一个函数1,有局部变量:参数;
(2)定义一个函数2,有局部变量:变量;
(3)调用函数,观察程序执行效果。
print('--------局部变量-方法内部-----------')
# 定义在函数内部的变量称为局部变量,对外不可见
def func(a):
b = 20 # 局部变量
a = a +1 # 局部变量
print('a=',a)
print('b=',b)
# print(a) # 报错
# print(b) # 报错
func(10)
print('--------特殊情况-for内部-----------')
for i in range(10):
print(i)
print('i=',i) # for结束之后,这里的i可以访问,值为9
总结:
(1)局部变量只作用于局部作用域内。
(2)通常地,根据变量作用域的不同,可以把变量分为:局部变量、全局变量。
2、全局变量
全局变量指的是:在函数体内、外都能生效的变量。
通俗地说,与模块中定义的函数,处于同一级别的变量,就是全局变量。
全局变量语法:
变量名 = 值
def 函数名():
代码
...
# 变量名 = 值
说明:
(1)全局变量是指与函数处于同一级别的变量;
(2)注意:当函数中的局部变量与全局变量同名时,在函数中使用的是局部变量的值。
需要注意的是,当要修改全局变量的值时,记得提前使用global进行声明。
global关键字语法:
# 声明
global 变量名
# 修改值
变量名 = 修改后的值
例如,一起来完成:
(1)定义一个全局变量1,并在函数内外都使用;
(2)定义一个同名的全局变量2和局部变量,并在函数内使用该同名变量;
(3)执行程序,观察效果。
print('--------全局变量-----------')
# 定义在函数内部的变量称为局部变量,对外不可见
a = 10 # 全局变量
def func():
print(a) # 函数内部访问全局变量
print(a) # 函数外部访问全局变量
func()
print('--------全局变量-----------')
a = 10 # 全局变量
def test1():
a = 20 # 局部变量,是一个新的变量,不是对全局的a进行赋值
print('函数内部:a=', a) # 20
print('函数外部:a=', a) # 10
test1()
print('--------全局变量-global-----------')
a = 10 # 全局变量
# 如果你希望在函数的内部去修改全部变量的值,则需要使用global
def test1():
global a # 告诉解释器,这里的a是全局变量
a = 20 # 我希望这里不是局部变量,而是对全局变量重新赋值
print('函数内部:a=', a) # 20
test1() # 先调用,才会修改全部变量
print('函数外部:a=', a) # 20
总结:
(1)当要定义一个作用在整个模块的变量时,就可以使用全局变量;
(2)注意:当要在函数内部给全局变量修改值时,需要先使用global关键字来声明。
五、函数的多种参数
1、位置参数
位置参数指的是:调用函数时,根据函数定义的参数位置来传递数值。
位置参数语法:
def 函数名(参数1,参数2,...):
代码
...
函数名(值1,值2,...)
说明:
当调用函数时,要按照定义函数时的参数位置,进行传递值。
例如,一起来完成:
(1)定义一个使用格式化符号替换数据,且显示姓名、年龄的函数;
(2)调用函数,展示形成【个人名片】的样式。
print('-----------1、位置参数-------------------')
def show_infos(name, age):
print("========================")
print("显示个人信息如下:")
print("姓名:%s" % name)
print("年龄:%d" % age)
print("========================")
# 位置参数,实参会按照先后顺序依次的传递给形参
show_infos('刘备', 18)
总结:
(1)在给位置参数传递值时,要注意参数的位置、类型和顺序;
(2)注意:有时候采用位置参数传递值时,比较麻烦,就可以使用关键字参数。
2、关键字参数
关键字参数指的是:调用函数时,可以通过【键 = 值】的形式指定参数。
使用关键字参数后,可以让函数更加清晰、容易使用,同时也简化了传递参数的要求,比如不需要关注参数的个数、类型和顺序。
关键字参数语法:
def 函数名(参数1,参数2,...):
代码
...
函数名(参数1=值, 参数2=值,...)
说明:调用函数时,参数名必须要与定义函数时的名称保持一致。
例如,一起来完成:
(1)定义一个函数,用于显示个人名片的姓名、年龄、性别等信息;
(2)当调用函数时,使用关键字参数的形式传递值。
print('-----------2、关键字参数-------------------')
# 1.定义显示个人信息的函数
def show_infos(name, age, sex):
print("个人信息如下:")
print(f"姓名:{name}")
print(f"年龄:{age}")
print(f"性别:{sex}")
show_infos('刘备', 18, '男') # 位置传参,要考虑顺序
show_infos(name='刘备', age=18, sex='男') # 关键字传参,不用考虑参数顺序
show_infos(sex='男', age=18, name='刘备') # 关键字传参,不用考虑参数顺序
show_infos(sex='男') # 报错,必须给所有参数赋值
总结:
(1)当传递关键字参数时,可以使用【键 = 值】形式来指定参数;
(2)请问:当采用关键字参数传递值时,可以不关注参数的顺序,这句话正确吗?==A、正确==;B、错误。
3、缺省参数
有时候,缺省参数也叫默认参数。
缺省参数是指:在定义函数时,就为参数提供默认值。
与此同时,在调用函数时,就可以不用传递默认参数的值。当然了,如果给缺省参数传递了数值,则以传递的值为准。
缺省参数语法:
def 函数名(参数1,参数2,...,参数n=值):
代码
...
函数名(值1,值2,...[值n])
说明:缺省参数需要定义在最末尾。
例如,一起来完成:
(1)定义一个显示姓名、年龄、性别的函数,且默认性别为男;
(2)调用函数,观察程序执行结果;
(3)思考1:可以定义多个缺省参数吗?
(4)思考2:能否把缺省参数放在前面呢?
print('-----------3、缺省(默认)参数-------------------')
# 默认参数只能放在参数列表的最右边,有默认值的参数,可以传值,也可以不传入值
# 1.定义显示个人信息的函数
def show_infos(name, age, sex='男'):
print("个人信息如下:")
print(f"姓名:{name}")
print(f"年龄:{age}")
print(f"性别:{sex}")
show_infos('刘备', 18) # 位置传参,有默认值的可以不用传入
show_infos('小乔', 18, '女') # 位置传参,覆盖默认值
show_infos(name='刘备', age=18) # 关键字传参,有默认值的可以不用传入
print('-----------3、缺省(默认)参数2-------------------')
# 1.定义显示个人信息的函数
def show_infos(name, age=18, sex='男'):
print("个人信息如下:")
print(f"姓名:{name}")
print(f"年龄:{age}")
print(f"性别:{sex}")
show_infos('小乔')
show_infos('小乔', 17)
show_infos('小乔', 17,'女')
总结:
(1)若给函数定义了缺省参数,则在调用函数时可以省略该参数值的传递;
(2)缺省参数必须定义在其他参数的最末尾处,这句话正确吗?==A、正确==;B、错误。
4、不定长参数
有时候,不定长参数也叫可变参数。
通常情况下,不定长参数用于在不确定调用函数时,要传递多少个参数的场景,当然也可以不传递参数。
而当要调用函数时,可以给*args传递位置参数,给**kwargs传递关键字参数,这样显得更加方便。
不定长参数语法:
def 函数名(参数1,..,*args,**kwargs):
代码
...
函数名(值1, 值2, 值3, ... 参数1=值, 参数2=值,...)
例如,一起来完成:
(1)定义函数1,使用不定长参数*args求多个数之和;
(2)定义函数2,使用不定长参数**kwargs求多个数之和;
(3)综合两个函数,合并在一起完成求多个数之和;
(4)执行程序,观察效果。
print('-----------1、*args-------------------')
# 该函数是一个变参函数,传入参数必须使用位置传参
def my_sum(*args): # 将传入的多个参数封装到元组中 args = (1,2,3)
print(type(args)) # 元组
return sum(args)
print(my_sum()) # 0
print(my_sum(1)) # 1
print(my_sum(1, 2)) # 3
print(my_sum(1, 2, 3)) # 6
# --------------------------------------
def my_sum(num1, *args): # 将传入的多个参数封装到元组中 args = (1,2,3)
return sum(args)
print(my_sum(1)) # 1 -> 1给了num1 ,args没有值
print(my_sum(1, 2)) # 2 -> 1给了num1, 2给了args
print(my_sum(1, 2, 3)) # 5 -> 1给了num1, 2和3给了args
print('-----------2、**kwargs-------------------')
# 该函数是一个变参函数,传入参数必须使用关键字传参
def my_sum(**kwargs): # 将传入的多个参数封装到字典中
print(type(kwargs)) # 字典类型:<class 'dict'>
print(kwargs) # {'num1': 1, 'num2': 2, 'num3': 3}
my_sum(num1=1, num2=2, num3=3)
# ------------------------------------------
def my_sum(num, **kwargs): # 将传入的多个参数封装到字典中
print(type(kwargs)) # 字典类型:<class 'dict'>
print(kwargs) # {'num1': 1, 'num2': 2, 'num3': 3}
my_sum(888, num1=1, num2=2, num3=3) # 888 给了num,剩下的给kwargs参数
my_sum(num=888, num1=1, num2=2, num3=3) # 888 给了num,剩下的给kwargs参数
# my_sum(888,1, 2, 3) # 报错,不能使用位置传参
# ------------------------------------------
def my_sum(*args, sep='#'): # 将传入的多个参数封装到字典中
print(args)
print(sep)
my_sum(1, 2, 3, sep='$') # 1 2 3 给了 args, sep必须使用关键字传参
总结:
当给不定长参数传递数值时,可以理解为:就是综合运用位置参数和关键字参数来传值。
六、拆包和交换变量值
1、拆包
先来看看在现实生活中的拆包。比如,张同学背着背包来办公室上班后,需要从背包中拿出电脑、鼠标、数据线、电源线等,这个过程就是拆包!
接着,看一下在Python程序中的拆包:把组合形成的元组形式的数据,拆分出单个元素内容。
变量名1,变量名2,... = 结果
例如,一起来完成:
(1)在一个函数中,使用return返回求解最大值,最小值,平均值
(2)分别使用拆包方式来拆分数据。
# 需求:定义一个函数,传入一个数字列表,返回列表的最大值,最小值,平均值
# 1、定义函数
def get_list_result(list_name):
max_value = max(list_name)
min_value = min(list_name)
avg_value = sum(list_name) / len(list_name)
return max_value, min_value, avg_value # 返回的时元组
list1 = [1,2,3,4,5]
# 如果一个函数返回多个值,则可以使用多个变量来接受,被称为拆包
max_value,min_value,avg_value = get_list_result(list1)
print(max_value)
print(min_value)
print(avg_value)
总结:
(1)当要把一个组合的结果快速获取元素数据时,可以使用拆包来完成;
(2)注意:对列表、元组数据结果,都可以使用拆包方式。
2、交换变量值
使用拆包方式可以用于交换变量的值。
例如,一起来完成:
(1)有变量a、b,请完成变量之间值的交换;
(2)使用引入第三方变量的形式完成数值的交换;
(3)使用拆包方式完成数值交换。
print('-----------交换两个数的值:方式1-----------')
a = 10
b = 20
c = a
a = b
b = c
print(f'a = {a}')
print(f'b = {b}')
print('--------交换两个数的值:方式2-------------')
a = 10
b = 20
a,b = b,a
print(f'a = {a}')
print(f'b = {b}')
总结:
交换两个变量的方式较多,但最简单的是:直接使用拆包方式交换值。
七、引用
1、了解引用
引用可以通俗的称为内存地址值。在Python中,引用有两种表现形式:
(1)十进制数 5040624
(2)十六进制数 0x45AC6
注意:在Python中,变量值是通过引用来传递的。
查看引用语法:
id(变量名)
说明:
我们可以把id()值理解为变量所在内存的地址值。
例如,一起来完成:
(1)定义一个变量a,查看变量的引用值;
(2)思考:有两个列表变量[1, 2],分别使用==和is去比较,结果如何?
# 引用
a = 10
b = 10
# 获取a存放的地址,也就是10这个数存放的内存地址
print(id(a)) # 140735745131056
print(id(b)) # 140735745131056
a = 20
print(id(a)) # 140735719572336
print('---------列表:可变,地址不同---------------')
list1 = [1,2,3]
list2 = [1,2,3]
print(id(list1)) #2301155693064
print(id(list2)) #2301155693576
print(list1 is list2 ) # 判断list1的地址和list2的地址是否相同
print('---------元组:不可变,地址相同---------------')
tuple1 = (1,2,3)
tuple2 = (1,2,3)
print(id(tuple1)) #1919263510840
print(id(tuple2)) #1919263510840
print(tuple1 is tuple2 ) # 判断tuple1的地址和tuple2的地址是否相同
print('---------字符串:不可变,地址相同---------------')
str1 = 'hello'
str2 = 'hello'
print(id(str1)) # 2087414306736
print(id(str2)) # 2087414306736
print(str1 is str2 ) # 判断str1的地址和str2的地址是否相同
总结:
对于可变类型,即使内容相同,地址值不同,对于不可变类型,内容相同,地址值也相同
注意:
比较两个变量的值是否相等时,使用==;比较两个变量的内存地址值是否相同时,使用is关键字。
2、把引用当做参数传递
我们知道,当定义函数时设定了参数,则在调用函数时也需要传递参数值。
而实际上,当给函数传递参数时,其本质就是:把引用当做参数进行传递。
例如,一起来完成:
(1)定义有一个参数的函数,并在调用函数时传递一个参数值;
(2)同时输出参数值与在函数内的参数的引用值,对比效果。
def func(b): # 实参a将地址传递给了形参b,a和b都指向同一片空间,也就是10存放的空间
print(id(b)) # 140735748014640
print(f'b={b}')
a = 10
print(id(a)) # 140735748014640
func(a) # 引用传递,传入的是地址值
总结:
当把变量传递给函数时,本质上是:传递变量的引用值。
八、匿名函数
1、lambda语法
定义匿名函数需要使用lambda关键字,可以创建小型匿名函数。
匿名函数表示没有名字的函数,这种函数得名于省略了用def关键字声明函数的标准步骤。
定义匿名函数语法:
lambda 参数列表 : 表达式
调用匿名函数语法:
函数名 = lambda 参数列表 : 表达式
函数名([参数列表])
例如,一起来完成:
(1)求解两个数之和;
(2)使用def定义函数,完成求和操作;
(3)使用匿名函数简化函数求和操作。
# 1、普通函数:求两个数的和
def add(num1, num2):
return num1 + num2
print(add(10, 20))
# 2、匿名函数:求两个数的和
# lambda 参数列表 : 表达式
# num1, num2表示匿名函数的参数, num1 + num2 表示函数的返回值
add2 = lambda num1, num2: num1 + num2 # add2其实是函数的名字
print(add2(10, 20))
总结:
当且仅当只需要调用使用一次时,可以优先使用匿名函数来完成。
注意:
匿名函数在实际应用中使用较少,了解即可。
2、lambda的应用
在实际应用中,为便于简化函数传递处理,我们可以使用lambda表达式作为参数进行传递,但要注意:传递的是一个引用。
在Python中,匿名函数通常使用lambda
表达式来创建。但是,需要注意的是,lambda
表达式仅用于编写单行的、简单的函数体。如果需要多条语句的函数体,应该使用def
关键字来定义一个常规的函数,而不是使用lambda
。
再来看一下匿名函数的语法。
定义语法:
lambda 参数列表 : 表达式
调用语法:
函数名 = lambda 参数列表 : 表达式
函数名([参数列表])
例如,一起来完成:
(1)把lambda表达式当作参数传递给函数;
(2)求解两个数之和,注意:在函数中定义变量并传递。
# 1.定义函数
def get_sum(func): # func = lambda a,b:a+b
x = 100
y = 998
print(f"求和:{func(x,y)}")
print('-----------将匿名函数作为参数传递----------------------')
# 2.调用 -传递匿名函数过去
# 可以把引用当作参数直接传递 -闭包
get_sum(lambda a,b:a+b) # lambda的匿名函数,只能是单行,而且这个单行就是函数的返回值
print('-----------将有名函数作为参数传递----------------------')
def add(a,b):
return a + b
get_sum(add)
总结:
(1)当要定义一个匿名函数时,需要使用lambda关键字
(2)当完成一个功能简单的需求时,可以使用匿名函数,而当需求较复杂时,不建议使用匿名函数。
【思考】使用函数形式来求解某天是该年的第几天?比如,2023年3月5日是2023年的第64天。
提示:要区分闰年、平年,闰年指的是能被4整除且不能被100整除,或者能被400整除的年份。
print('----------------------方式1--------------------------')
# 1.定义函数: 求是否是闰年
def is_run_year(year):
"""
判断是否是闰年
:param year: 年份
:return: 是闰年 True; 不是闰年: False
"""
if (year % 4 == 0) and (year % 100 != 0) or (year % 400 == 0):
return True
return False
# 2.求解第几天: 之前月份的总天数+当前日期
def get_days(year, month, day):
days = 0
# 判断年份
# if is_run_year(year):
if is_run_year(year) == True:
day_lists = [0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30]
else:
day_lists = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30]
# 通过月份数求解之前月份的总天数
temp_ret = 0
i = 0
while i < month:
temp_ret += day_lists[i]
i += 1
# +当前日期
days = temp_ret + day
return days
# 3.输入年月日、调用函数
in_year = int(input("请输入年份:"))
in_month = int(input("请输入月份:"))
in_day = int(input("请输入日期:"))
print(f"{in_year}年{in_month}月{in_day}日是{in_year}年的第{get_days(in_year,in_month,in_day)}天.")
print('----------------------方式2--------------------------')
def is_leap_year(year):
"""
判断是否是闰年
:param year: 年份
:return: 是闰年返回 True; 不是闰年返回 False
"""
return (year % 4 == 0 and year % 100 != 0) or (year % 400 == 0)
def get_day_of_year(year, month, day):
"""
计算某天是该年的第几天
:param year: 年份
:param month: 月份
:param day: 日期
:return: 某天是该年的第几天
"""
days_in_month = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
if is_leap_year(year):
days_in_month[1] = 29 # 如果是闰年,二月份有29天
days = sum(days_in_month[:month - 1]) + day # 累加前几个月的天数,并加上当前月的天数
return days
# 示例
print(get_day_of_year(2023, 3, 5)) # 输出应该是 64