1.函数的介绍
函数:实现某个功能的代码段
函数的作用:可以对功能代码进行服用,减少代码的冗余
2.函数的定义和调用
函数定义的语法格式
def 函数名():
实现某个功能的一段代码
提示:函数定义完成以后,不会主动调用函数里面的功能代码,需要程序员手动调用函数,才会执行函数里面的代码
调用函数的语法格式
函数名()
def show(): # 遍历range时,数据不需要使用,可以使用下划线进行占位。 for _ in range(3): print("人生苦短,我用python!") # 调用函数,执行函数里面的功能代码 show() print("xxxxx" * 10) show()
3.函数的文档说明
函数的文档说明:把多行注释放到了函数内的第一行,该注释称为是文档说明
函数文档说明的作用:对函数的功能进行解释说明,告诉开发者函数的功能职责是什么
import random
def show_info():
"""我是函数的文档说明"""
print("哈哈,今天学习了函数,好开心!")
# 查看函数的文档说明,可以使用help函数
# help(要查看的函数名)
# help(show_info)
help(random.randint)
# 补充:
def sum_num(num1, num2):
"""
实现对两个数字完求和操作
:param num1: 第一个数字
:param num2: 第二个数字
:return: 求和的数据
"""
result = num1 + num2
return result
4.带有参数的函数
带有参数的函数的语法格式
def 函数名(形参1, 形参2, ...):
实现相关功能的代码
函数名(实参1, 实参2, ...)
形参:在定义函数时设置的参数称为形参
实参:在调用函数时设置的参数称为实参
提示:函数定义时设置形参的目的是在调用函数时需要接收实参。
# 带有参数的函数
def sum_num(num1, num2):
result = num1 + num2
print("结果为:", result)
sum_num(10, 30)
print("over")
# 总结:
# 带有参数的函数,只需要在定义函数时设置形参即可
# 函数的执行流程
5.带有返回值的函数
带有返回值的函数的语法格式
def 函数名():
实现代码
return 数据 # 这里返回的数据就是返回值
因为函数调用后有返回值,需要使用变量保存这个返回值
result = 函数名()
print(result)
def sum_num(num1, num2):
value = num1 + num2
# print("函数内使用value,该数据为:", value)
# 通过return 把函数内的value返回给调用者
return value
# 使用result变量,来保存sum_num函数调用后返回的结果
result = sum_num(1, 2)
print("函数返回的结果为:", result)
6.python提供的内置函数
内置函数:不需要导入模块或者包直接使用的函数,称为内置函数
len: 统计容器类型中元素的个数 ***
max: 返回容器类型中的最大值
min: 返回容器类型中的最小值
del: 删除指定的变量,一旦删除完成以后,后续再次使用这个变量名
my_list = ['A', "C", "E"]
# 使用变量保存len函数调用后的结果
result = len(my_list)
print("列表中元素的个数为:", result)
my_tuple = (1, 0, 5)
max_value = max(my_tuple)
print("返回的最大值为:", max_value)
min_value = min(my_tuple)
print("返回的最小值为:", min_value)
my_name = "李四"
print(my_name)
# 删除指定变量
# del(my_name)
# 提示:删除指定变量还可以通过del关键字来完成
del my_name
print(my_name)
7.函数的嵌套调用
函数的嵌套调用:在一个函数内部再次调用其他函数的格式。
总结: 不管直接调用还是嵌套调用函数,函数的执行流程不变。
函数的执行流程:
1.当调用函数时,先回到函数的定义,给函数的形参赋值
2.当形参赋值完成以后,会执行函数里面的代码
3.当函数里面的代码执行完成以后,表示函数执行结束,代码会回到之前函数调用的地方,然后代码在继续往下
执行。
def task1():
print("task1函数开始执行啦...")
print("task1")
print("task1函数执行结束啦...")
def task2():
print("task2函数开始执行啦...")
# 调用task1
task1() # 这里就使用了函数的嵌套调用
print("task2")
print("task2函数执行结束啦...")
task2()
8.局部变量
局部变量: 在函数内定义的变量称为局部变量
局部变量的作用:临时存储函数内某个数据, 当函数执行结束后局部变量会销毁释放对应的内存
局部变量的使用范围: 只能在当前函数内使用,不能在函数外或者其它函数内使用
def show_info():
# 局部变量
name = "李四"
# 在当前函数内使用这个局部变量
print("姓名:", name)
show_info(
9.全局变量和修改全局变量
全局变量:在函数外定义的变量,称为全局变量
全局变量的作用:可以在不同函数之间共享全局变量的数据
全局变量的使用范围:可以在不同函数之间使用,相当于在当前的这个python文件中可以使用
# 定义全局变量
num = 10
def task1():
print("task1函数内使用全局变量的数据为:", num)
def task2():
print("task2函数内使用全局变量的数据为:", num)
task1()
task2()
print(num)
修改全局变量
#需求:在函数内修改全局变量
g_num = 100
def modify_value():
# 声明要修改全局变量,这里不是再定义一个局部变量啦
global g_num
g_num = 200
# 本意是要修改全局变量,但是这里其实是定义了一个局部变量,只不过局部变量的名字和全局变量的名字相同而已
# g_num = 200
print("在函数内修改全局变量,修改后全局变量的数据为:", g_num)
modify_value()
# 再次访问全局变量的时候,该数据应该是修改后的数据200
print("再次访问全局变量:", g_num)
# 总结:
# 在函数内修改全局变量需要使用global关键字
10.函数之间共享数据的操作
函数之间共享数据的操作
1. 使用全局变量
2. 通过函数的返回值
g_score = 100
def show_msg():
print("show_msg 访问全局变量的数据为:", g_score)
def show_info():
print("show_info 访问全局变量的数据为:", g_score)
show_msg()
show_info()
def return_data():
msg = "ok"
return msg
def show_data():
# 获取返回值
result = return_data()
print("结果为:", result)
def info():
# 获取返回值
result = return_data()
print("info结果为:", result)
show_data()
info()
11.函数返回多个值
return特点 :
# 1.当函数执行完return语句以后,表示函数执行结束,return后面的代码不会执行
# 2.return语句只能返回1次。
# return想要返回多个数据,需要结合容器类型使用,把多个要返回的数据放到容器类型里面,返回容器类型的数据即可。
def return_more_value():
# return [1, 2]
# return {"num1": 1, "num2:": 2}
# return (1, 2)
# 返回多个数据的简写方式
return 1, 2 # 返回的是一个元组
result = return_more_value()
print(result, type(result))
# 总结:函数想要通过return返回多个数据,可以结合容器类型来完成。
12.缺省参数
缺省参数:在定义函数时,给形参进行赋值,那么该形参称为缺省参数
缺省参数的特点: 当调用函数时,给缺省参数设置值了,则使用设置的数据,否则使用默认值
缺省参数的注意点: 缺省参数后面可以在跟上缺省参数,不能再跟上普通的形参。
def sum_num(num1, num2=10, num3=30):
value = num1 + num2
return value
# result = sum_num(1, 2)
# print("结果为:", result)
result = sum_num(1)
print("结果为:", result)
13.调用函数的三种传参方式
调用函数时的参数传参方式
1. 按照位置参数的方式进行传参, 注意点:位置参数顺序一定要和函数定义时形参的顺序保持一致
2. 按照关键字参数的方式进行传参, 注意点:关键字的名字一定要和函数定义时形成的名字保持一致
3. 按照复合参数(前面使用位置参数,后面使用关键字参数)的方式进行传参
注意点: 一旦前面使用关键字参数,那么后面就不能再使用位置参数了,只能使用关键字参数
def show_info(name, age, sex): print("姓名:", name, "年龄:", age, "性别:", sex) # 按照位置参数的方式进行传参 ========= # show_info("李四", 20, "男") # 注意点:位置参数顺序一定要和函数定义时形参的顺序保持一致, 下面是错误写法 # show_info("李四", "男", 20) # 按照关键字参数的方式进行传参 ========== # show_info(name="王五", age=30, sex="男") # 按照关键字参数的方式进行传参不强调关键字参数的顺序 # show_info(name="王五", sex="男", age=30) # show_info(name="王五", sex="男", age1=30) # 按照复合参数(前面使用位置参数,后面使用关键字参数)的方式进行传参 ====== # show_info("李六", 20, sex="男") # 注意点:按照复合参数的方式进行传参是,一旦前面使用关键字参数,那么后面就不能再使用位置参数了,只能 # 使用关键字参数 show_info("张三", age=30, sex="男")
14.不定长参数
不定长参数:在定义函数时,不确定接收参数的个数,此时可以使用不定长参数
不定长参数的表现形式
1. *args: 表示在调用函数时,专门来负责接收不确定个数的位置参数的。
2. **kwargs:表示在调用函数时,专门来负责接收不确定个数的关键字参数的。
# 定义一个带有不定长位置参数的函数
# 提示:可以修改args的名字,但一般不改
# def show_info(*args):
# print(args, type(args))
# 当调用函数的时候,会把所有的位置参数打包到一个元组里面,然后把元组赋值给args,也就是说args是元组类
# show_info(1, 2)
# 定义一个带有不定长关键字参数的函数
# def show_info(**kwargs):
# print("kwargs:", kwargs, type(kwargs))
# 当调用函数时,会把所有的关键字参数打包到一个字典里面,然后把字典赋值给kwargs,也就是说kwargs是字典
# show_info(a=1, b=2)
# 定义一个函数带有不定长位置参数和不定长关键字参数
def show_info(*args, **kwargs):
print("args:", args, type(args))
print("kwargs:", kwargs, type(kwargs))
# show_info(1, 2)
# show_info(c=1, d=2)
# show_info(1, 2, a="张三", b="李四")
show_info()
15.解包传参
def show_info(name, age, sex):
print("name:", name, "age:", age, "sex:", sex)
my_tuple = ("李四", 20, "男")
# # *my_tuple: 表示对元组进行解包传参,把元组中的每一个数据按照位置参数的方式进行传参
# show_info(*my_tuple) # =》 show_info("李四", 20, "男")
my_dict = {"name": "王五", "age": 30, "sex": "男"}
# **my_dict: 表示对字典进行解包传参,把字典中的每项数据按照关键字参数的方式进行传参
show_info(**my_dict) # => show_info(name="王五", age=30, sex="男")
16.缺省参数结合不定长参数
注意点:
1.当缺省参数结合不定长位置参数一起使用的时候,需要把缺省参数放到不定长位置参数(*args)的后面
2.当不定长关键字参数结合其它参数一起使用的时候
# 当缺省参数结合不定长位置参数一起使用的时候,需要把缺省参数放到不定长位置参数(*args)的后面
# def show_info(name, *args, age=18):
# print("name:", name, "age:", age, "args:", args)
#
#
# # show_info("李四", 20, 1, 3, 4)
# show_info("李四", 1, 3, 4)
# show_info("李四", 1, 3, 4, age=20)
# 当不定长关键字参数结合其它参数一起使用的时候,那么不定长关键字参数(**kwargs)需要放到所有参数的最后面
def show_info(name, *args, age=18, **kwargs):
print("name:", name, "age:", age, "args:", args, "kwargs:", kwargs)
# show_info("李四", 1, 3, 5, a=5, b=6)
# 注点意:当使用关键字进行传参的时候,先判断有没有对应的形参,如果有把数据给形参,否则给**kwargs参数
# show_info("李四", 1, 3, 5, a=5, b=6, age=30)
show_info("李四", 1, 3, 5, age=20, a=5, b=6)
17.拆包
拆包:使用不同变量保存容器类型中的每一个数据的操作,称为拆包
拆包的目的:获取容器类型中的每一个数据
my_list = ["A", "B", 3] # 利用拆包,使用三个变量分别保存列表中的每一个数据 value1, value2, value3 = my_list print(value1, value2, value3) my_dict = {"name": "吕布", "age": 30} # 对字典直接进行拆包,获取的key # data1, data2 = my_dict # print(data1, data2) data1, data2 = my_dict.values() print(data1, data2)
18.交换两个变量的值
num1 = 3
num2 = 5
print("num1:", num1, "num2:", num2)
# 通用写法,交换两个变量的值 =================
# temp = num1
# num1 = num2
# num2 = temp
#
# print("num1:", num1, "num2:", num2)
# 利用拆包,交换两个变量的值 =========================
# num1, num2 = num2, num1
# print("num1:", num1, "num2:", num2)
# # 1. 先把num2和num1组装到一个元组
# result = num2, num1
# print(result, type(result))
# # 2. 利用拆包,重新给num1和num2赋值
# num1, num2 = result
# print("num1:", num1, "num2:", num2)
# 先把num2,num1进行组包操作,然后再利用拆包,交换两个变量的值
num1, num2 = num2, num1
print("num1:", num1, "num2:", num2)
19.引用
引用:变量对数据内存地址的使用称为引用, 通俗理解变量使用了某个内存地址称为引用该数据的内存地址
提示:变量最终保存的是数据在内存中的一个地址,也就是说变量保存的是内存地址, 数据都是保存在内存里面
内存地址:就是数据在内存中的一个物理位置, 通过内存地址可以在内存中找到对应的数据。
# 严格来说,定义了一个变量,存储的是数据1在内存中的地址。
num1 = 1
# id函数是用来查看变量保存的内存地址
num1_id = id(num1)
print("num1:", num1, "num1保存的内存地址:", num1_id)
# 定义了一个变量,名字是num2, 保存的是num1存储的内存地址。也就是说这个两个变量引用的是同一个内存地址。
num2 = num1
num2_id = id(num2)
print("num2:", num2, "num2保存的内存地址:", num2_id)
# 重新给num1赋值, 修改了变量保存的引用
num1 = 10
num1_id = id(num1)
print("num1:", num1, "num1保存的内存地址:", num1_id)
print("num2:", num2, "num2保存的内存地址:", num2_id)
20.可变类型
可变类型:允许在原有内存空间的基础上修改数据,修改后数据的内存地址不变
可变类型有: 列表,字典,集合
name_list = ["西施", "貂蝉"]
print("修改前:", name_list, id(name_list))
# name_list.append("杨玉环")
del name_list[-1]
print("修改后:", name_list, id(name_list))
person_dict = {"name": "关羽", "age": 30}
print("修改前:", person_dict, id(person_dict))
person_dict["age"] = 40
print("修改后:", person_dict, id(person_dict))
21.不可变类型
不可变类型: 不允许在原有内存空间的基础上修改数据,修改后数据的内存地址会发生变化
不可变类型: 数字,字符串,元组,range
my_str = "abc"
print("修改前:", my_str, id(my_str))
# 错误写法
# my_str[-1] = 'f'
# print(my_str)
# 替换字符串后会返回一个新的字符串
# new_str = my_str.replace("c", "f")
# print("修改后:", new_str, id(new_str))
# print("修改后:", my_str, id(my_str))
# 通过重新赋值,来修改数据,相当于修改变量的引用
my_str = "abf"
print("修改后:", my_str, id(my_str))
my_num = 100
print("修改前:", my_num, id(my_num))
# 重新赋值,相当于修改变量的引用
my_num = 200
print("修改后:", my_num, id(my_num))
# 总结:对于不可变类型来时,修改数据只能重新赋值,相当于修改变量的引用。
22.+=操作的本质
+=操作的本质是要在原有内存空间的基础上修改数据,前提是该数据是可变类型
注意点:
1.如果数据是可变类型,+=后 数据的内存地址不变
2.如果数据是不可变类型,+=后 数据的内存地址会发生变化
def modify_value(params):
print("修改前:", params, id(params))
params += params
print("修改后:", params, id(params))
# 可变类型的变量 =======
# my_list = [1, 2]
# print("my_list", my_list, id(my_list))
# modify_value(my_list) # params = my_list
# 不可变类型的变量
my_num = 10
print("my_num", my_num, id(my_num))
modify_value(my_num) # params = my_num
# 在python里面所有的赋值操作都是按照引用传递,就是按照内存地址传递的
23.函数使用的注意事项
1. return注意点
1.1 当函数或者方法执行完return关键字以后,表示函数或者方法执行结束,return后面的代码不会执行
1.2 return只能返回1次数据
1.3 return关键字只能在函数或者方法内使用,不能单独使用
2. 函数名相同的注意点
2.1 函数名相同,会把之前的函数进行覆盖
3. 变量作用域的注意点
3.1 局部变量只能在当前函数内使用
3.2 全局变量可以在不同函数或者函数外使用,相当于在当前的python文件中可以使用。
24函数结合return让多层循环终止
def show():
for data in range(0, 11, 2):
print("外层循环生成的数据为:", data)
for value in range(1, 7, 2):
print("内层循环生成的数据为:", value)
if value == 3:
# 当函数一旦执行return语句以后,则函数执行结束
return
show()
25.global关键字的本质
global 关键字的本质:表示声明要修改全局变量的引用,其实说白了就是要修改全局变量保存的内存地址。
不管是可变类型还是不可变类型只要对全局变量进行重新赋值,那么都需要在函数内加上global
# g_list = []
#
#
# # 通过函数修改全局变量的数据
# def modify_value():
# # 因为g_list是列表类型,它属于可变类型,修改数据后内存地址不变。
# # 这里并没有对g_list变量的引用进行修改,所以不需要加上global
# # g_list.append("李四")
# # 在函数里面对全局变量进行重新赋值操作,相当于修改了全局变量的引用,需要加上global
# global g_list
# g_list = ["李四"]
# print("函数修改后全局变量的数据为:", g_list, id(g_list))
#
#
# print("修改前:", g_list, id(g_list))
# modify_value()
# print("修改后:", g_list, id(g_list))
# 不可变类型全局变量的使用 ==================
g_num = 10
def modify_value():
# 表示声明要修改全局变量的引用,
global g_num
g_num = 20
print("函数修改后全局变量的数据为:", g_num, id(g_num))
print("修改前:", g_num, id(g_num))
modify_value()
print("修改后:", g_num, id(g_num))
26.递归函数
递归函数: 在一个函数内部再次调用函数本身,该定义的函数称为递归函数
注意点: 递归函数不能无限制的自己调用自己,必须要有结束递归调用条件
递归函数的形参条件:
1. 在函数内部调用函数本身
2. 必须要有结束递归调用条件
# 递归函数的定义
def show(count):
print("哈哈,今天学习递归函数啦...")
# count == 1 就是结束递归调用的条件,当满足这个条件是不需要再自己调用函数本身啦
if count == 1:
print("递归结束:over")
else:
# 在函数内部,再次调用函数本身
show(count - 1)
# 调用show函数
show(3)
27.匿名函数
匿名函数:使用lambda关键字定义的函数,称为匿名函数,有的地方说没有名字函数就是匿名函数
学习匿名函数的目的:简化之前普通函数的功能代码
匿名函数的特点:
1.匿名函数只能写一行代码
2.匿名函数的返回值不需要加上return
3.匿名函数也是函数,在调用匿名函数的时候也需要加上()
匿名函数的语法格式:
lambda 形参1, 参数2,...: 返回值或者调用其它函数
# 使用def定义一个函数,实现求两个数字的和
def sum_num(n1, n2):
return n1 + n2
# result = sum_num(1, 2)
# print(result)
# ============== 使用匿名函数对以上函数的功能代码进行简化 ===========
# 为了后续使用匿名函数更加方便,一般会使用变量来保存匿名函数
new_func = lambda x, y: x + y
print("new_fun变量的类型:", type(new_func))
print("sum_num函数的类型:", type(sum_num))
result = new_func(1, 2)
print("结果为:", result)
# 定义一个无参数无返回值的匿名函数
my_func = lambda: print("人生苦短,我用python!")
my_func()