本文内容包括:函数基本语法、函数参数、返回值、函数作用域及函数嵌套、递归、匿名函数、重要内置函数、高阶函数
一、函数基本语法及特性
定义: 函数是指将一组语句的集合通过一个名字(函数名)封装起来,要想执行这个函数,只需调用其函数名即可
def 函数名(参数1,参数2)
''' 函数注释'''
print('函数体')
return 返回值
相关概念:
1、def关键字开头,空格之后接函数名和圆括号,最后还要加一个冒号。
2、def是定义函数的关键字,固定的,不能变。
3、函数名:函数名是包含字母,数字,下划线的任意组合,但是不能以数字开头。虽然函数名可以随便取名,但是一般尽量定义成可以表示函数功能的。
特性:
减少重复代码
使程序变的可扩展
使程序变得易维护
例如:
def add(b,a):
print(a) #a=7,不是等于5,因为传参数时5传给吧b,7传给a,顺序传值
print(b)
return a+b
result=add(5,7)#实参,接收返回值
print(result) #12
二、函数参数
函数的有三中不同的参数:
1)位置参数
2)默认参数
#、必须参数name,age
def print_info(name,age,sex='male'):#默认参数:sex='male',调用参数不用,默认参数放在其他参数的放后面。
print('Name : %s,Age : %d,Sex : %s'%(name,age,sex))
print_info('XiaoHu1',23) ##默认参数
print_info('XiaoHu2',23)
print_info('XiaoHu3',23)
print_info('XiaoHu4',23,'female') # 指定参数
运行结果:
Name : XiaoHu1,Age : 23,Sex : male
Name : XiaoHu2,Age : 23,Sex : male
Name : XiaoHu3,Age : 23,Sex : male
Name : XiaoHu4,Age : 23,Sex : female
3)不定长参数(动态参数)
1、按位置传值多余的参数都由args统一接收,保存成一个元组的形式
2、按关键字传值接受多个关键字参数,由kwargs接收,保存成一个典的形式
3、传参数的时候:必须先按照位置传参数,再按照关键字传参数
def add(*args):#*args接受不定长的参数,无命名参数
print(args)#做成一个元组数据
add(1,2,3,4)
#运行结果:
#(1, 2, 3, 4)
4)不定长参数实现加法:
不定长参数1:
def add(*args):#*args是不定长的参数或者动态参数,*args是接收无命名参数
print(args)#做成一个元组数据
sum=0
for i in args:
sum=sum+i
print(sum)
add(1,2,57)
#结果:
#(1, 2, 57)
#60
不定长参数2:
def print_info(**kargs):#加参数是键值对时,**kargs是针对有命名参数
for i in kargs:
print('%s:%s'%(i,kargs[i]))
#有命名的参数放在**kargs空字典里面。
print_info(age=23,sex='女',hobby='basktball',job='studengt')
运行结果:
age:23
sex:女
hobby:basktball
job:studengt
不定长参数3:
def print_info(*args,**kargs):#加参数是键值对时,*args是接收无命名参数(xiaohu1),**kargs是有命名参数,针对有命名参数,无命名参数:放在左边,有的放在右边
for i in kargs:
print('%s:%s'%(i,kargs[i]))
print(args)#以元组形式输出
#传参数的时候:必须先按照位置传参数,再按照关键字传参数
#没有命名的参数放在*args空元组里面,有命名的参数放在**kargs空字典里面
print_info('XiaoHu1',age=23,sex='女',hobby='basktball',job='studengt')
运行结果:
age:23
sex:女
hobby:basktball
job:studengt
('XiaoHu1',)
切记: 参数的优先级: 位置参数,*args, 默认参数,**kwargs
例如:
#参数的位置优先级
def f (name,*args,age=23,**kwargs):
##位置参数,*args, 默认参数,**kwargs
pass
4)不定长参数接收字典
def f(*args,**kwargs):
print(args)
print(kwargs)
f(1,2,3,**{'name':'alex'},age=23)#直接传一个字典
运行结果:
(1, 2, 3)
{'name': 'alex', 'age': 23}
三、 返回值
获取函数的执行结果,就可以用return语句把结果返回调用者
函数返回值分为有返回值和没有返回值。
1、有返回值
1.return的作用:结束一个函数的执行
2.首先返回值可以是任意的数据类型。
3.函数可以有返回值:如果有返回值,必须要用变量接收才有效果
4.return返回一个值(一个变量)
5.return返回多个值(多个变量):多个值之间用逗号隔开,以元组的形式返回。
2、、没有返回值:
没有返回值的时候分三种情况:
1.当不写return的时候,函数的返回值为None
2.当只写一个return的时候,函数的返回值为None
3.return None的时候,函数的返回值为None(几乎不用)
接收:可以用一个变量接收,也可以用多个变量接收,返回几个就用几个变量去接收
例如:返回值返回什么就是什么。
1、返回return
def f():
print('ok')
return 2
a=f()
print(a) #2
#如果没有返回则自动返回None
#return返回值给调用者f(),只想拿到这个值。
2、返回None:
def add(*args):#*args接受不定长的参数,无命名参数
sum=0
for i in args:
sum=sum+i
a=add(1,2,57)
print(a)#打印a时,因为没有返回值return,所以系统自动返回None
3、返回对个值时封装成元组形式
def foo():
return 1,'243',0
print(foo()) #1,'243',0封装成元组里面。
注意:
1、函数没有return,默认返回一个None
2、如果return多个对象,那么帮我们把多个对象封装成一个元组对象返回。
四、函数作用域及函数嵌套
在说函数作用域之前,来看看下面的例子
if True:
a=10
print(a) #10
def f():
a=10
f()
print(a)#报错,因为函数有作用域
#注意:在python里面函数是有作用域的,if是没有的。
一、函数的作用域
1、命名空间
在将函数的作用域之前先来了解命名空间。
命名空间分为全局命名空间、局部命名空间和内置命名空间。
全局命名空间:定义在类外或者函数外的变量所存储的空间。
局部命名空间:在函数里临时创建的空间叫做局部命名空间
内置命名空间:python解释器内置有的空间:input,print,list等
例如:
a=10
def f():
a=a+1
f()
print(a)#报错,UnboundLocalError: local variable 'a' referenced before assignment
2、作用域:就是作用范围
1、命名空间和作用域是分不开的
2、作用域分为两种:
全局作用域:全局命名空间与内置命名空间的名字都属于全局范围在整个文件的任意位置都能被引用,全局有效
局部作用域:局部命名空间,只能在局部范围内生效
3、全局作用域:
使用变量的时候:如果全局有,用全局。如果全局没有,用内置的
4、global方法:
a=10
def f():
global a#把a强制转换x为全局变量,声明global
a=a+1
f()
print(a)
#结果:11
为什么a的值可以改变?因为在局部空间用了global方法,使得把a强制转换x为全局变量。
5、nonloca方法l
让内部函数中的变量在上一层函数中使用和修改
def count():
count = 10 #enclosing
def inner():
nonlocal count#作用域,嵌套此时在嵌套的函数里面修改count时,count的值时被修改后存在count里面。
count = count+3 #local
print(count)
inner()
print(count)
count()
五、递归
定义:一个函数在内部调用本身,这个函数就是递归函数。
递归的特征:
1、调用自身函数
2、有一个结束条件
1、用函数实现n!
例1:
def facet(n):
result=1
for i in range(1,n+1):
result=result*i
print(result)
facet(3)
用递归函数实现例1:
#递归函数
def facet(n):
if n==1:
return 1
return n * facet(n-1)
facet(3)
例3:斐波那契数列:0 1 1 2 3 5 8 13 21 34 55
def feibo(n):
if n==0:
return 0
elif n==1:
return 1
else:
return feibo(n-1)+feibo(n-2)
print(feibo(5))
六、匿名函数
1、匿名函数
1)、参数可以有多个,用逗号隔开
2)、返回值和正常的函数一样可以是任意的数据类型
七、重要内置函数
1、map方法
str=['d','b','c','a']
def fun2(s):
return s+'alvin'#['dalvin', 'balvin', 'calvin', 'dalvin']
ret=map(fun2,str)#元组,这时b,c,d放在ret这个空间,你不用就装在迭代器中,
# map的作用就是把str序列作为参数传到fun1中,过滤并
print(ret) #<map object at 0x00000000025AD198>
print(next(ret)) #dalvin
for i in ret:
print(i)
运行结果:
<map object at 0x00000000025AD198>
dalvin
balvin
calvin
aalvi
可以看出ret是一个map对象,因此需要迭代器对象转换成列表时就以列表形式返回,也可以调用next()方法,,也可以利用for循环一个一个的输出。
2、filter
str=['a','b','c','d']
def fun1(s):
if s !='a':
return s
ret=filter(fun1,str)#元组,这时a,b,c,d放在ret这个空间,你不用就装在迭代器中,
#filter的作用就是把str序列作为参数传到fun1中,并遍历str和对str过滤,不会改变
print(ret)
print(list(ret))#ret是迭代器对象转换成列表时就以列表形式返回
运行结果:
<filter object at 0x000000000254D198>
['b', 'c', 'd']
3、reduce,需要导入模块from functools import reduce
例1:
from functools import reduce
def add1(x,y):
return x+y
print(reduce(add1,[1,2,3]))#先把前两个数传过去在返回,再传返回值和后面实现叠加
print(reduce(add1,range(1,101)))#先把前两个数传过去在返回,再传返回值和后面实现叠加
运行结果:
6
5050
例2:
from functools import reduce
print(lambda x,y:x*y,range(1,4)) #<function <lambda> a t 0x00000000003B2EA0> range(1, 4)
print(reduce(lambda x,y:x*y,range(1,4)))#6、lambda匿名函数 格式:lambda a,b:a+b
运行结果:
<function <lambda> at 0x00000000004C2EA0> range(1, 4)
6
八、高阶函数
1、函数名可以作为函数参数
def f(n):#一个函数的名字相当于是一个变量,存的函数对象的内存地址
return n*n
def foo(a,b,func):
return func(a)+func(b)
print(foo(1,2,f))
#结果:5
2、函数名可以作为函数的返回值
def foo():
def iner():
return 8
return iner
ret=foo()
print(ret())
#结果 8
结论:
1、函数名可以进行赋值,因为它是一个变量
2、函数名可以作为函数参数,可以作为函数的返回值。