文章目录
1、函数的作用
函数就是将⼀段具有独⽴功能的代码块 整合到⼀个整体并命名,在需要的位置调⽤这个名称即可完成对应的需求,函数在开发过程中,可以更⾼效的实现代码重⽤。
2、函数的定义与调用
2.1、定义
def 函数名(参数):
函数体
例如
def fun(a, b):
return a-b;
2.2、调用
函数名(参数)
例如调用上面定义的函数
print(fun(3, 2))
输出
1
注意:
1、不同的需求,参数可有可无
2、在Python中,函数必须先定义后使用
3、函数必须被调用才会执行
3、函数参数的作用
可以是我们的程序更加灵活,需要注意的是,定义函数的时候的参数也叫形式参数(形参),调用时传入的参数叫实际参数,也叫做实参,且调用的时候传入的实参的个数必须与形参的个数相同
4、函数返回值的作用
在函数中,如果需要返回结果给⽤户需要使⽤函数返回值
语法
return 想要的返回值
注意,return后面的代码都不会再执行,因为return后就会退出当前函数,回到调用函数的地方继续向下执行
5、函数的说明文档
5.1、help
help(函数名):查看函数的说明文档(函数的解释说明的信息)
5.2、定义函数的说明文档
语法
def 函数名(参数):
"""说明文档的位置"""
代码
...
例如
def fun():
"""输出HelloWorld"""
print("HelloWorld")
help(fun)
输出
Help on function fun in module __main__:
fun()
输出HelloWorld
6、函数的嵌套调用
函数的嵌套调用就是在一个函数1里面又调用了函数2(函数2可以是函数1本身,也可以是其他函数)
函数的嵌套调用不难,我们只需要知道函数的执行流程即可
函数的执行流程:
1、调用函数,回到函数的定义处
2、自上而下执行函数体里的代码,遇到return或函数体里面的代码执行完后就退出函数
3、回到函数的调用处,继续向下执行下面的代码
看下面的代码
def fun1():
print("fun1函数开始执行")
print("fun1函数结束执行")
def fun2():
print("fun2函数开始执行")
fun1()
print("fun2函数结束执行")
fun2()
输出
fun2函数开始执行
fun1函数开始执行
fun1函数结束执行
fun2函数结束执行
7、变量的作用域
变量的作用域就是指变量的生效范围,因此变量又分为局部变量和全局变量
7.1、局部变量
即定义在缩进里面的变量,只在缩进的那一段代码里生效,用于临时保存数据,当执行完缩进里面的代码后,局部变量就会被销毁
7.2、全局变量
所谓全局变量,就是指从定义处开始,到程序结束运行时都会生效的代码
接下来我们看两个例子
a = 100
print(a)
def fun1(a):
a = 200
print(a)
fun1(a)
print(a)
print("============================================")
b = [1, 2]
print(b)
def fun2(b):
b[0] = 100
print(b)
fun2(b)
print(b)
输出
100
200
100
============================================
[1, 2]
[100, 2]
[100, 2]
我们可以看到一个很有意思的现象,那就是当我们把a的值100传入进函数fun1时,a的改变也只是在函数外面改变,当函数结束运行时,原本a的值100并未发生改变,可是当我们传入一个列表a时,我们改变里面其中一个元素的值,列表a也跟着改变,这是为什么呢?
这时候我们就需要注意,当我们给函数传入参数时,传入的是一个值还是一个地址,接下来我们对上面的两个案例进行分析
首先是函数fun1()
当我们传入参数a时(我们假设这个a的地址为1111),我们是将a的值100传给函数的形参a,这个时候调用函数fun1的时候,函数就会在内存中单独开辟一个空间,并在这个空间中为形参分配一个内存空间,我们假设这个a内存空间的地址为2222,并将传入的实参给这个地址,如图所示
当我们执行到代码a = 200时,我们修改的只是函数开辟的这片空间里面a的值,地址为1111的a的值并未受到任何影响
此时我们输出的a的值也只是函数开辟的空间里面的值,当函数执行完后,函数临时开辟的这一片空间就会被销毁,我们再输出a的值,输出的就是全局变量,也就是地址为1111的这片空间的地址的值100
我们再说说函数fun2
同样,我们在刚开始就定义了一个全局变量b,由于它是列表,我们假设这一片连续的空间的地址为3333
当我们执行函数fun2时,此时传入的是列表b的地址3333,此时函数虽然会单独开辟一片空间用来执行函数里面的代码,却不会再为b单独开辟一个地址,而是就全局变量b的地址进行操作,修改的时候也是对3333这片连续的空间里面的值进行修改,所以在函数fun2执行完毕之后,我们再输出列表b里面每个元素的值,列表b也会发生改变
最后提一下,当我们有很多重名的变量名的时候,我们在调用某个变量名时,遵循的是就近原则,即距离调用处越近的,我们就越先调用,就好像上面的fun1时,我们在函数体内部打印a时,打印的是200而不是100
global函数
作用:声明某个变量为全局变量
语法
global 变量名
a = 100
print(a)
def fun1():
# global a
a = 200
print(a)
fun1()
print(a)
当我们将global a这行代码注释掉后,控制台输出的是
100
200
100
当我们将注释取消后,控制台输出的是
100
200
200
由此我们可以观察到,global可以在函数体内部声明某个变量为全局变量,这样,当调用该变量时,就会调用刚开始定义的变量,这里我们需要注意的是,在函数体内部声明某个变量为全局变量时,改变量不能是函数的形参,否则将会报错,例如下面的代码
def fun1(a):
global a
a = 200
print(a)
这样会报错
SyntaxError: name 'a' is parameter and global
8、函数的返回值
当我们想要在一个函数中返回多个值,那我们便可以这样书写
def 函数名(参数):
代码1
代码2
retrun 返回值1, 返回值2
注意:
1、return a, b写法,返回多个数据的时候,默认是元组类型
2、return后面可以连接元组、列表、或字典,以返回多个值
9、函数的参数
9.1、位置参数
位置参数:调⽤函数时根据函数定义的参数位置来传递参数
def fun(name, age):
print(f'名字:{name}, 年龄:{age}')
fun('TOM', 20)
注意:传递和定义参数的顺序及个数必须⼀致
当定义参数的个数与传入参数的个数不一致会报错
def fun(name, age):
print(f"姓名:{name},年龄:{age}")
fun("Tom")
TypeError: fun() missing 1 required positional argument: 'age'
当传入参数的顺序与定义的顺序不一致时,可能不会报错,但会导致数据无意义
def fun(name, age):
print(f"姓名:{name},年龄:{age}")
fun(19, "Tom")
姓名:19,年龄:Tom
9.2、关键字参数
函数调⽤,通过“键=值”形式加以指定。可以让函数更加清晰、容易使⽤,同时也清除了参数的顺序需求
def student_info(name, id, grade):
print(f"学号:{id}")
print(f"姓名:{name}")
print(f"成绩:{grade}")
student_info("小明", grade=99, id=1111)
学号:1111
姓名:小明
成绩:99
注意:函数调⽤时,如果有位置参数时,位置参数必须在关键字参数的前⾯,但关键字参数之间不存在先后顺序
def student_info(name, id, grade):
print(f"学号:{id}")
print(f"姓名:{name}")
print(f"成绩:{grade}")
student_info(grade=99, "小明", id=1111)
该代码报错
SyntaxError: positional argument follows keyword argument
这样也会报错
def student_info(name, id, grade):
print(f"学号:{id}")
print(f"姓名:{name}")
print(f"成绩:{grade}")
student_info(99, name="小明", id=1111)
TypeError: student_info() got multiple values for argument 'name'
即如果我们要部分参数不写成关键字参数而留成位置参数,这些位置参数也必须是前面的,因为位置参数只能写在关键字参数前面
9.3、缺省参数
缺省参数也叫默认参数,⽤于定义函数,为参数提供默认值,调⽤函数时可不传该默认参数的值
def student_info(name, grade, ID="0000"):
print(f"学号为{ID}的学生姓名是{name},成绩为{grade}")
student_info("小明", 99)
student_info("小红", 100, "1111")
学号为0000的学生姓名是小明,成绩为99
学号为1111的学生姓名是小红,成绩为100
注意:
1、所有位置参数必须出现在默认参数前,包括函数定义和调⽤,因为默认参数也是一种关键字参数
2、函数调⽤时,如果为缺省参数传值则修改默认参数值;否则使⽤这个默认值
9.4、不定长参数
不定⻓参数也叫可变参数。⽤于不确定调⽤的时候会传递多少个参数(不传参也可以)的场景。此时,可⽤包裹(packing)位置参数,或者包裹关键字参数,来进⾏参数传递,会显得⾮常⽅便。
9.4.1、包裹位置传递
语法:
def 函数名(*args):
函数体
这里的args可以为其他合法的标识符(变量名)只不过写成这样是一个习惯
def fun(*args):
print(args)
fun()
fun("Tom")
fun("Tom", 19)
()
('Tom',)
('Tom', 19)
注意:
1、传进的所有参数都会被args变量收集,它会根据传进参数的位置合并为⼀个元组(tuple),args是元组类型,这就是包裹位置传递。
2、当有位置参数混合传递时,位置参数必须放在不定长参数的前面
def fun(*args, name):
print(name, args)
fun("Tom", 19)
TypeError: fun() missing 1 required keyword-only argument: 'name'
9.4.2、包裹关键字传递
语法:
def 函数名(**kwargs):
函数体
这里的kwargs可以为其他合法的标识符(变量名)只不过写成这样是一个习惯
即收集所有关键字参数返回一个字典
def fun(**kwargs):
print(kwargs)
fun()
fun(name="Tom", age=18)
{}
{'name': 'Tom', 'age': 18}
注意:
1、同上面一样,当有位置参数时,位置参数的定义与调用都必须在不定长参数的前面
def fun(**kwargs, age):
print(age, kwargs)
# fun()
fun(name="Tom", age=18)
报错
SyntaxError: invalid syntax
2、当有其他关键字参数参与时,这种传递方式不会收集该参数
def fun(age, **kwargs):
print(age, kwargs)
# fun()
fun(name="Tom", age=18)
18 {'name': 'Tom'}
由上面我们可以知道,不定长参数其实都是一个组包的过程