1、函数的介绍
-
函数的定义:
-
def 函数名(参数):
函数体
return 返回值
-
-
函数的调用:函数名(参数)
# 函数: 将特定的功能所对应的代码片段进行打包,封存在一个函数内,如果我们想要重复使用该功能,就直接调用函数即可
# 函数的作用: 提高代码复用率,提高开发效率,易于维护
'''
函数定义的格式:
def 函数名(参数1, 参数2,参数3....):
函数体
return 返回值
函数调用的格式:
函数名(参数1,参数2,参数3.....)
# 函数名:绝大多数函数都有函数名,没有函数名的函数不能被复用
# 参数:为了让函数灵活性更高,更容易被复用,会动态对函数进行传值,传递的值可以在函数体内部进行使用
# 函数体: 特定功能的代码,写在函数内部,调用函数时可全部执行
# 返回值: 写在return之后,将函数内部计算或运行得到的数据传递到函数体外部
'''
# 定义的时候可以不传参,如果不传调用的时候也不用传参
def run():
print('我跑的老快了,没人追的上我,钱包在我手里')
print('我跑的老快了,没人追的上我,手机在我手里')
print('我跑的老快了,没人追的上我,女朋友在我手里')
# 调用时可以将函数内的代码全部执行一遍
run()
run()
-
函数的调用顺序:从上到下依次执行,先键函数名保存到函数列表中,调用的时候去类表中查询,如果存在则调用其中的代码,如果不存在则报错
# NameError: name 'sing' is not defined
# 函数需要先定义后调用否则会报错
# sing()
# 定义一个唱歌方法
def sing():
print('我再唱青藏高原')
# 定义一个跳舞方法
def dance():
print('我再跳广场舞')
sing()
dance()
# 执行顺序: 先讲所有函数的函数名执行一遍将其储存到缓存中的方法列表中,后续调用函数时去方法列表中查询,如果函数名存在,则调用函数内部的代码,如果函数名不存在将报错
2、函数的参数
函数的参数可以增加代码的灵活性
-
在定义时传入的参数是形参,只能在函数体内部使用
-
在调用的时候传入的参数是实参,可以传入到函数体内部被形参接收
# 定义一个eat方法,通过传入不同的参数,可以输出不同的生物吃不同的食物
def eat_cat():
print('猫吃鱼')
def eat_dog():
print('狗吃肉')
def eat_person():
print('人吃藕')
# 上述函数定义方法不太方便,因为如果有更多的生物去吃不同的东西,就要重复书写函数不利于函数的复用
# 改进 >> 传参
# 通过传入参数,可以控制函数体内部的执行结果发生变化,让函数更加灵活
def eat(who, food): # 在定义时传入的参数叫做形参,只能在函数体内部使用
print(f'{who}吃{food}')
# 在调用的时候传入的参数叫做实参,会传入到函数内部被形参接收
eat('猫', '🐟')
eat('狗', '肉')
eat('人', '藕')
# TypeError: eat() missing 1 required positional argument: 'food'
# 进行传值时需要保证传参数量满足要求,否则会报错
# eat('人')
3、函数的返回值
-
1.返回值是将函数内计算或运行的结果返回到函数外部调用位置,参与计算或运行
-
2.函数可以不写返回值或者只写一个return不写返回值内容,都会默认返回一个None
-
3.return后将会立即跳出函数,如果在retrun后仍有代码,则不会被执行
-
4.return只能返回一个元素,如果想返回多个元素需要使用容器类型
# 返回值:将函数体内部运行或计算得到的数据传递到函数体外部
# def sum(a, b):
# print(a + b)
#
#
# sum(1, 2)
# 思考?如果我们想在函数体外部使用这个结果进行二次运算我应该怎么做?
# NameError: name 'a' is not defined a, b 是形参,只能在函数体内部使用
# print(a + b)
# 如果我们想将数据传递出来可以使用return
def sum1(a, b):
return a + b
print(sum1(1, 3)) # 当函数执行完毕,函数调用位置就替换为函数的返回值
# 返回的数据可以参与计算
print(sum1(1, 3) + 12)
# 注意:返回值内容不会自动打印到控制台,将数据返回后如果想要查看数据需要手动打印或者debug调试
# 如果没有return 那么就没有返回值么?
list1 = [1, 2]
# 因为此处,append方法,没有返回值,默认返回None
print(list1.append(3)) # None
def eat():
print('猫吃鱼,狗吃肉,奥特曼吃小怪兽')
# 如果没有书写返回值,则返回值为None
print(eat()) # None
# 如果只写了return 没有写返回值内容会怎么样? None
def sum1(a, b):
print(a + b)
return
print(sum1(1, 2)) # None
# return 执行后会跳出函数,return之后的所有代码将不会继续执行
# 在函数中可以有多个return 但是只能执行一个
def function():
print('hello python')
return
return
# 同一分支中,在return之后的所有代码不会被执行
print('hello bigdata')
function()
# 返回值只能是一个么? 可以返回多个返回值么?
# 返回值只能是一个元素,如果要返回多个值只能通过容器类型进行打包
def function1():
return 1, 2, 3, 4
print(function1()) # (1, 2, 3, 4)
# 结论:
'''
1.返回值是将函数内计算或运行的结果返回到函数外部调用位置,参与计算或运行
2.函数可以不写返回值或者只写一个return不写返回值内容,都会默认返回一个None
3.return后将会立即跳出函数,如果在retrun后仍有代码,则不会被执行
4.return只能返回一个元素,如果想返回多个元素需要使用容器类型
'''
4、函数的嵌套
-
在一个函数体内部嵌套了另一个函数的调用
# 函数的嵌套,就是在一个函数的内部嵌套了另一个函数的调用
def function2():
print('我是func2-----')
function1()
print('我是func2-----')
def function1():
print('func1执行开始')
print('func1执行结束')
# def function2():
# print('我是func2-----')
# function1()
# print('我是func2-----')
function2()
# 执行顺序,只要函数在调用之前被定义即可,定义函数的顺序不做规定
5、函数的局部变量和全局变量
-
局部变量就是在函数体内部进行定义函数体外部无法调用的变量
-
全局变量就是在函数体外部,一般在文件顶格处书写,函数体内外都可以使用的变量
-
if 和for结构中的控制语句中定义的变量都是全局变量
# 全局变量就是在函数体外部书写的一般要在文件内顶格书写,在函数体内部外部都可以调用的变量
a = 1
b = 2
def sum1():
# 函数体内部可以使用
print(a + b)
sum1()
# 函数体外部也可以使用
print(a)
print(b)
# for 循环中, if 分支中创建的变量是全局变量还是局部变量呢? 全局变量
# for i in range(10):
# pass
#
# print(i)
#
# if True:
# c = 1
# print(c)
6、gloal声明全局变量
-
global能声明我们当前使用的变量是全局变量
-
LEGB原则
-
L:在函数体内部查找
-
E:在外层函数中查找
-
G:在全局变量中查找
-
B:在内置变量中查找
-
# global 全局 :作用就是声明我要使用的这个变量是全局变量
# 如果要在函数体内修改全局变量,就要使用global
a = 100
# 此处,使用a=1相当于再函数体内定义了一个局部变量,并没有修改全局变量的值
# def func1():
# a = 1
# 如果想要在函数体内修改全局变量就要使用global
# def func1():
# global a
# a = 1
#
# func1()
# print(a)
# 扩展: 在Python中所有的变量查询遵循legb原则
# 调用变量时的查询顺序
'''
L:local :首先在函数体内部查询
E:edge :在外部函数中查询
g:global:在全局变量中查询
b:built-in:在系统内置变量中查询
'''
def func1():
# L:我们再调用变量时,先在函数体内部查找
a = 1
print(a)
func1()
def out_func():
# E: 如果当前函数中没有此变量,我们将在外部函数中查找
a = 2
def in_func():
print(a)
in_func()
out_func()
def func2():
# 如果函数体内部和外部函数中都没有该变量,则去全局变量中查找
print(a)
func2()
# 当这个函数在函数体内部,外部函数中,全局变量中都不存在时, 则去内置变量中查找
print(__name__) # __main__
def func3():
# a = a + 10
# 首先用a + 10 进行计算,根据legb原则先从函数体内部查找,查找后发现a 在函数体内部定义,但是在调用时未定义则报错
# a += 10
# print(a)
a = 1
def func4():
# SyntaxError: name 'a' is assigned to before global declaration
# 如果要对全局变量进行修改,则先对变量进行global修饰,在修改,否则报错
a = 15
# global a
func4()
print(a)
# 能否在函数体内部创建全局变量 可以 只要用global修饰即可
def func5():
global num1
num1 = 105
func5()
print(num1)
7、函数的参数进阶
-
位置参数:直接书写参数名,在传值时顺序传值,调用时既不能多传参,也不能少传参(形参)
-
关键字参数:使用”参数名 = 值“的形式进行传参(实参)
-
可以不按顺序赋值
-
必须在顺序赋值之后完成赋值
-
-
缺省参数:在定义函数时,给参数一个默认值,如果调用时,不给其传参,则使用默认值,如果传参,则使用传入的值
# 位置参数:按照位置顺序进行赋值的参数(形参)
def func(a, b, c, d):
print(a)
print(b)
print(c)
print(d)
# TypeError: func() missing 1 required positional argument: 'd'
# 如果有位置参数没有被赋值,则报错
# func(1, 2, 3)
# TypeError: func() takes 4 positional arguments but 5 were given
# 如果位置参数传参过多也会报错
# func(1, 2, 3, 4, 5)
# 结论:位置参数在使用时需要保证每个参数都被赋值,且不要重复赋值或赋多个值
# 在为位置参数顺序赋值时,所有的参数按序赋值给每个位置参数
func(1, 2, 3, 4)
# 关键字参数 : 关键字参数就是通过"参数名 = 值"的形式进行赋值的参数(实参)
def func(a, b, c, d):
print(a)
print(b)
print(c)
print(d)
# 使用关键字参数,不需要按照顺序赋值,只要参数名称正确即可
func(d=4, a=1, c=3, b=2)
# 使用参数=值的形式赋值,就是关键字参数
# func(a=1, b=2, c=3, d=4)
# TypeError: func() got an unexpected keyword argument 'f'
# 使用关键字参数赋值时,要注意所使用的参数是否存在,最好是提示出来在用
# func(f=1, b=2, c=3, d=4)
# 注意:使用关键字参数要防止重复赋值
# TypeError: func() got multiple values for argument 'a'
# func(1,2,3,a=5)
# 一般情况下,关键字参数都是给默认参数(缺省参数)赋值的
# 缺省参数:就是在定义时给参数一个默认值,如果参数没有赋值,则使用默认值
def func(a, b, c, d=10):
print(a)
print(b)
print(c)
print(d)
# 不给缺省参数传值则使用默认值
# func(1, 2, 3)
# 给缺省参数传值则使用传入的值
# func(1, 2, 3, 4)
# 一般使用关键字参数给缺省参数赋值
# func(1, 2, 3, d=12)
# 关键字参数赋值,不能在顺序赋值之前
# func(d=12,1, 2, 3)
8、函数的不定长参数
-
位置不定长参数(*args):多余的位置参数,可以被args接收,并且打包为一个元组,保存在args当中。
-
# 不定长参数主要就是在定义函数时,不确定参数的个数时即可进行不定长参数的书写 ''' 位置不定长参数的定义格式: def 参数名(*args): 函数体 ''' # def func(*args): # print(*args) # 相当于书写内容为 print(1,2,3) # # # func(1, 2, 3) # print(1, 2, 3) # args变量到底内部是什么样子的? # def func(*args): # return args # 数据传入函数内部时,将传入的多个数据进行打包,转换为一个元组,被args接收.并且在函数体内部可以使用该元组参与运算 # print(func(1, 2, 3)) # (1, 2, 3) # 案例: # 输入不确定数量的多个值,判断其中的最大值 def max1(*args): max_num = args[0] # 如果max_num = 0 这个时候我们所有值都没负的时候会判断出错 for i in args: if i > max_num: max_num = i return max_num print(max1(1, 4, 5, 3, 6, 12, 3)) # 如果输入的数值全部为负呢? print(max1(-1, -2, -5))
-
关键字不定长参数(**kwargs):将多余的关键字 参数,打包为一个字典,保存在kwargs当中
# 关键字不定长参数,可以接收多个未定义参数的关键字赋值
'''
关键字不定长参数的格式:
def 函数名(**kwargs):
函数体
'''
# TypeError: 'a' is an invalid keyword argument for print()
# def func(**kwargs):
# print(**kwargs) # 相当于给print输入了多个关键字参数 print(a=1, b=2, c=3)
#
#
# func(a=1, b=2, c=3)
# 使用**kwargs可以将关键字参数进行传递
# def func(**kwargs):
# print(1, 2, **kwargs) # 相当于print(1, 2, sep='&', end='a')
#
#
# func(sep='&', end='a')
# kwargs 内部到底是什么存储结构呢?
def func(**kwargs):
# kwargs 在从传参之后,会将实参位置的所有未定义参数的关键字参数转换为字典的键值对,保存在kwargs当中
print(kwargs) # {'a': 1, 'b': 2, 'c': 3}
func(a=1, b=2, c=3)
# 案例:
# 使用创建一个函数可以保存学员的全部信息,并将其储存到字典当中
def student_info(**kwargs):
print(f'学员信息为:{kwargs}')
student_info(name='xiaoming', age=18, gender='男')