函数
1.定义
- 函数时一段具有特定功能的,可以重用的语句组。
- 函数是一种功能的抽象,一般函数表达特定功能。
- 一个自定义函数完全符合IPO方法,也就是说有输入,处理过程,输出(当然有些函数输入可以为空)
2.作用
- 降低编程难度
- 代码复用
- 代码可读性
3.定义格式
def <函数名>(<参数(0个或多个)>) :
<函数体>
return <函数返回值>
例如下面这个求绝对值的函数:
def fact(n):
if n < 0:
return -n
else:
return n
4.函数调用
例如调用上面的求绝对值函数:
a=int(input())
print(a)
b=fact(a)
print(b)
调用时要给出实际参数,用来替换定义中的参数,参数不能少或多,另外函数的返回值赋值给对应的变量(在上面的例子中,返回值就赋值给了b)
5.函数参数
函数可以有多个参数,也可以没有参数,但必须保留括号,格式如下:
def fact():
print("Hello World")
函数定义时可以为某些参数指定默认值,构成可选参数(默认值参数),格式如下:
def <函数名>(<非可选参数>,<可选参数>) :
<函数体>
return <函数返回值>
例如:
def f(n,m=1) :
a=n-m
return a
//在这个函数中,f(10,5)的返回值为5(m=1是在默认情况下也就是我没有指定m的值的时候,这里我指定了m=5因此默认值1也就没用了),f(10)的返回值是9
5.参数传递
参数传递有两种方式:
- 位置传递
第一个实参赋值给第一个形参,第二个实参赋值给第二个形参(对应位置赋值),… - 关键字传递(名称传递)
形参m只找实参中m的值
例如:
def f(n,m) :
a=n-m
return a
//f(10,1)的返回值为9,这是位置传递
//f(m=1,n=10)的返回值也为9,这是关键字传递(如果按照位置传递的话返回值为-9)
注意:1.使用关键字参数传递可以不管参数的前后位置顺序。2.两种传递混合使用时,位置参数传递放前面。这句话的意思就是f(10,m=1)的表达是可以的,f(m=1,10)这样的表达是不可以的。
6.不定长参数
函数定义时可以设计可变数量参数,即不确定参数总数量,这样的参数传递方法叫做包裹传递,格式如下:
def <函数名>(<参数>,*args) :
<函数体>
return <函数返回值>
#这里的*和元组拆包中的*的作用类似,都表示不确定的数量
注意:1.不定长参数写在参数列表的后面。2.是不定长参数的标志,参数名为后面的变量名。3.args接受到的数据存放在元组中。
例如:
#不定长参数
def f(headman,*args):
print('组长为{},组员有:{}'.format(headman,args))
f('张飞','a1','a2','a3')
f('关羽','b1','b2')
f('李白','c1','c2','c3','c4','c5')
运行结果如下:
组长为张飞,组员有:('a1', 'a2', 'a3')
组长为关羽,组员有:('b1', 'b2')
组长为李白,组员有:('c1', 'c2', 'c3', 'c4', 'c5')
#组员的返回值用()包含,说明是一个元组
7.带关键字的不定长参数
def <函数名>(<参数>,*args,**kwargs) :
<函数体>
return <函数返回值>
#这里的*和元组拆包中的*的作用类似,都表示不确定的数量
注意:1.带关键字的不定长参数写在参数列表的最后。2.
*
是标志,参数名为**后面的变量名。3.kwargs接收到的数据存放在字典中。
例如:
def f(headman,*args,**kwargs):
print('组长为{},组员有:{},辅导员阵容为:{}'.format(headman,args,kwargs))
kwargs={
"生活辅导员":"刘备","战斗辅导员":"关羽"}
args=('a1','a2','a3')
f('赵云',*args,**kwargs)
运行结果如下:
组长为赵云,组员有:('a1', 'a2', 'a3'),辅导员阵容为:{
'生活辅导员': '刘备', '战斗辅导员': '关羽'}
8.函数的返回值
- return保留字用来传递返回值;函数可以有返回值也可以没有返回值;return可以传递0个返回值,也可以传递任意多个返回值。
- 当函数返回多个值时,返回的值就构成一个元组,需要用其中的值时就可以利用元组拆包来分别赋值。
9.局部变量和全局变量
在某个函数内部定义的变量就是局部变量(包括形参),在函数外的就是全局变量。当某个局部变量和全局变量重名时,如果使用了该变量那么采用就近原则来选值。
规则一:局部变量和全局变量是不同变量
- 局部变量是函数内部的占位符,与全局变量可能重名但不同。
- 函数运算结束后,局部变量就被释放。
- 可以使用
global
保留字在函数内部使用全局变量。就相当于某个全局变量经过函数运算之后的值发生了改变。
规则二:局部变量为组合数据类型且未创建,等同于全局变量
例如:
ls=["F","f"] #创建了一个全局变量列表ls
def func(a):
ls.append(a) #此处ls是列表类型,没有创建过,所以就等同于全局变量
return
func("C") #全局变量ls被修改
print(ls)
10.lambda匿名函数
lambda
函数返回函数名作为结果
lambda
函数是一种匿名函数,即没有名字的函数- 使用
lambda
保留字定义,函数名是返回结果 lambda
函数用于定义简单的,能够在一行内表示的函数
使用格式:
<变量名> = lambda <参数>:<表达式>
上式等价于下面这段代码(当然前提是函数体足够简单,下面的代码才能转化为上面的lambda函数):
def <函数名>(<参数>):
<函数体>
return <返回值>
例如:
f = lambda x,y:x+y
print(f(10,5))
//运行结果为15
f = lambda:"lambda函数"
print(f())
//运行结果为lambda函数
另外还有一个作用见文章**《NO.4 03.23 元组,字典,集合》**的结尾部分
11.高阶函数——map()函数
定义:若某函数A的参数为另一个函数的函数名,则函数A称为高阶函数。
1.map()函数map(f,lt1,lt2...)
例如:
a=map(int,input().split())
功能:它接收一个函数f和一个可迭代对象(如列表),并通过把函数f依次作用在list的每个元素上,得到一个map类型的可迭代对象并返回。
例如:
#列表中的每个数求平方
lt=[1,2,3,4,5]
def f(x):
return x**2
a=map(f,lt)
print(list(a))
运行结果:
[1, 4, 9, 16, 25]
12.高阶函数——filter()函数(“过滤器”,“筛选器”)
格式为:filter(f,lt)
功能:它接收一个函数f和一个可迭代对象(如列表),序列的每个元素作为参数传递给函数,将返回True的元素返回。就是说在函数里面写一个判断语句,返回值是True的再返回来,将False的过滤掉。
例如过滤筛选出1-10之间的偶数:
def f(x):
if x%2==0:
return True
else:
return False
a=filter(f,range(1,11))
print(list(a))
#运行结果为[2, 4, 6, 8, 10]
另外要注意的就是
map()
函数和filter()
函数print输出结果时记得加上list()
13.递归函数
所谓递归就是函数在定义中嗲用函数自身的方式,在之前最常用的用到递归的地方就是求阶乘。
例如:
在函数的递归中,有两个关键特征:
- 链条:计算过程存在递归链条(递归体)。
- 基例:存在一个或多个不需要再次递归的基例(递归出口)。
例如,把上面的求阶乘写成Python函数的形式为:
def fact(n):
if n==0:#基例(递归出口)
return 1
else:
return n*fact(n-1)#链条(递归体)
递归本身就是一个函数,需要函数定义的方式描述。在函数的内部,采用分支语句对输入参数进行判断,对应的在基例和链条中分别编写代码。
斐波那契数列:
def fe(n):
if n==1 or n==2:
return 1#递归基例
else:
return fe(n-1)+f(n-2)#递归链条
汉诺塔:
count=0
def han(n,a,b,c):
global count
count+=1
if n==1:
print("{}:{}-->{}".format(n,a,c))
else:
han(n-1,a,c,b)
print("{}:{}-->{}".format(n, a, c))
han(n-1,b,a,c)
han(3,'A','B','C')
print(count)