目录
函数(function)
函数:如同定义变量一样,变量是对字符串对象进行定义。函数则是对一段代码进行定义,这段代码也属于对象,即定义的函数执行的对象。变量即变量名,定义的函数也就是函数名。我们给一段代码定义一个名字就是定义函数。解释器有它的内置函数,同时我们也可以自定义自己需要的函数。
函数定义的规则
- 函数定义以def 关键字开头,后面跟函数名和圆括号()。
- 圆括号里面存放定义的参数,需要传入的参数或者变量必须在圆括号中。
- 函数的第一行语句中可以使用三引号来说明函数。
- 函数体要缩进。
- return用来结束函数,函数中的执行语句在遇到return时,自动结束函数,不管后面有没有要执行的语句。return后面跟返回的表达式,没有return语句的函数默认返回None值(None为函数的缺省值)。return函数只用于自定函数内部,它的返回值常常用来被调用。参考python内置常量:https://docs.python.org/3/library/constants.html
语法格式
def 函数名(参数列表):
函数体
函数调用(执行函数)
要执行函数代码,需要调用函数,调用函数就是函数名后面加上括号。
函数的参数
定义函数名后面括号中的内容为参数,多个参数时,每个参数之间用逗号隔开。
参数的作用是:提供函数完成功能所必须的信息,在调用函数时写上对应的参数,参数相当于变量,执行代码时,直接将参数变量赋值给代码语句。
参数类型
必备参数、关键字参数、默认参数、不定长参数
必备参数:必备参数需要以正确的顺序和数量传入,调用函数的时候数量必须与声明时的一样。
关键字参数:函数调用的时候使用关键字来确定传入的参数值。使用关键字参数的时候允许参数的顺序和声明的不一致,解释器会根据参数名自行匹配参数。但是支持带参数名和不带参数混用,但是,一旦有参数被指定了参数名使用,后面的参数都需要指定对应的参数名。
默认参数:如果我们调用函数的某些参数一般情况下是某个固定的值,但偶尔也会使用其他的值,为了方便,使用缺省值可以在调用的时候不需要我们去写入参数,默认会使用缺省的参数值,而当使用其他值的参数时,调用函数的时候只需写入对应的参数值。简单来说,调用函数的时候,如果没有传递参数,解释器会使用函数在定义时声明的默认参数值(默认参数的缺省值)。如果传入了,则使用传入的参数值。默认参数的声明需要放在其他参数的后面。
不定长参数:经常会遇到一个函数要处理比声明时更多的参数,这些参数的数量并不固定,这就需要使用不定长参数,不定长参数可以为空,并且它的声明不需要命名。不定长参数有两种,一种是加一个星号*,一种是加两个星号**。如下面的代码:
def func(*args,**kwargs):
print(*args) # 使用*args传参时,会返回每个参数值,是一种解压缩的方式返回
print(args) # 使用args时,将传入的参数放在一个字典中返回出来
print(type(args)) # 通过打印得到使用args的返回对象的类型为元组
print(kwargs) # 使用kwargs,将变量与值的方式传进的数据放到一个字典中
print(type(kwargs)) # 通过打印得到kwargs的返回对象的类型为字典
func('a','b','c',x=8,y=9,z=10)
说明:加一个星号的参数是以元组的形式导入进行存放所有未命名的变量参数。如果在函数调用时没有指定参数,它就是一个空元组。我们也可以不向函数传递未命名的变量。加两个星号的参数是以字典的形式导入,传入的参数为变量名与变量的形式。
参数中单独的 * 和 / :
声明函数的时候参数中间可以单独出现星号*,单独出现星号,*后的参数必须是用关键字参数的形式传入。(参数中出现单独的*,声明*之后的所有参数必须使用关键字参数形式)
强制位置参数:python3.8开始,新增了一个函数形参语法,/ 用来指明函数形参必须使用指定位置参数,不能使用关键字参数的形式。(参数中出现单独的/,声明/之前的所有参数不能使用关键字参数形式)
匿名函数
将一个简单的函数写成一行的形式,python是使用lambda创建匿名函数的。需要说明的是:lambda的主体是一个表达式,而不是一个代码块。lambda 函数拥有自己的命名空间,且不能访问自己参数列表之外或全局命名空间里的参数。
语法: Lambda 参数:表达式 # 表达式为return的返回
匿名函数的调用:可以将其赋值给一个变量,调用的时候直接传入变量参数
fanc = Lambda 参数:表达式 # 可以将其赋值给一个变量,调用的时候直接传入变量参数
fanc(参数) # 调用
函数的作用域
函数的作用域就是函数在调用的时候,函数中的代码块所能访问和执行到的变量所在的区域。
作用域变量的访问规则
1、函数外部不能访问函数内部的变量,函数内部的变量叫做局部变量
def ddd():
a = 1 # 局部变量
return id(a),a
print(ddd()) # 内部访问
print(id(a),a) # 外部访问
2、函数内部可以访问到函数外部的变量,函数外部的变量叫做全局变量
a = 1 # 全局变量
def ddd():
return id(a),a
print('函数访问外部变量:',ddd())
print('外部变量:',id(a),a)
3、函数里面不能直接修改外面(全局)的变量(可访问不可修改),因为全局变量是对于整个文件起作用的,不会因为局部的使用操作而引起全局数据的错误。
4、函数里面和外面变量名相同时,如果值不同,id也不同(相同的变量名存储的地址不同,因为它们属于不同的作用域中,就如同不同目录下存储相同名称的文件),但当变量名和值都相同的时候,id也会相同。
补充说明:函数在使用变量的时候,需要搜索变量,如果同一变量名的变量在在函数的内外都有,即全局变量和局部变量具有同一变量名时,会使用局部变量,函数中对于变量的搜索顺序是先局部后全局。
变量的修改
修改全局变量:global
在函数里面修改全局变量时使用关键字:global
a = 1
print('打印源变量的变量值:%s,源变量的变量id:%s'%(a,id(a)))
def func1():
global a
a += 1
print('在函数里面打印函数中修改后的变量值:%s,修改后变量id:%s'%(a,id(a)))
func1()
print('在函数外面打印函数中修改后的变量值:%s,修改后变量id:%s'%(a,id(a)))
修改局部变量:nonlocal
函数嵌套中,内层函数修改外层函数的变量时使用关键字:nonlocal
def func_out():
a = 1
print('打印外层函数未修改前的变量值:%s,未修改前的变量id:%s'%(a,id(a)))
def func_in():
nonlocal a
a += 1
print('在内层函数中打印内层函数修改后的变量值:%s,修改后的变量id:%s'%(a,id(a)))
func_in()
print('在外层函数中打印内层函数修改后的变量值:%s,修改后的变量id:%s' % (a, id(a)))
func_out()
小知识:在对数据对象进行比较是否相等的时候,会使用到==或is,使用==比较的是数据的值是否相等,使用is是比较数据存储的内存地址是否相同。
str1 = 1
str2 = 1
print('使用==比较值相同的两个数据对象值的结果:',str1==str2)
print('使用is比较值相同的两个数据对象内存地址的结果:',id(str1) is id(str1))
内嵌函数与闭包
内嵌函数就是嵌套在函数内部的函数,通过在函数内部调用的方式调用,就是和上面修改局部变量的代码一样。
闭包的基础是函数嵌套,它是一种特殊的函数调用方式,是函数内外部之间沟通的桥梁。不同的是,闭包是外层函数返回内层函数的函数体,而不是返回调用内层函数后的结果。
def func1():
n = input('输入被除数:')
def func2():
m = input('输入除数:')
print('%s除以%s的值为:%s'%(n,m,int(n)/int(m)))
return func2
func = func1()
func()
函数的递归和回调
递归:函数调用本身,但是递归具有深度,需要有终止条件,(无限递归会报错)否则会报错(同循环中的判断,循环没有终止条件会死循环),如下代码:指定一个数,计算从0开始到这个数之间等差为1的所有数的和值
# 写法一:
def func1(x):
'''
计算从0到这个数之间等差为1的所有数之和
'''
if x >= 0:
return x + func1(x-1)
else:
return 0
# 写法二:
def func2(x):
'''
计算从0到这个数之间等差为1的所有数之和
'''
if x <= 0:
return 0
return x + func2(x-1)
print(func1(5))
print(func2(5))
如果没有条件限制,结果如下:
def func2(x):
return x + func2(x-1)
print(func2(5))
回调函数是在其他函数中被调用的函数,也可以当作参数被其他函数调用,如函数被装饰器装饰时。