函数进阶
递归函数
定义一个函数在函数的内部调用自身,如果不设置递归边界,将死循环无限调用知道被pycharm等ide观测到抛出异常终止
案例1:
def fun():
if n == 0:
return n
else:
return n*fun(n-1)
# 在当前函数中,就是当n=0的时候停止调用自身
纯函数
纯函数的概念,简单来说,一个函数的返回结果只依赖于它的参数,并且在执行过程里面没有副作用(副作用请看到后面),就吧这个函数叫做纯函数.
不管在什么时候调用,传入的参数相同,返回的结果就一定是一样的.
纯函数的三原则
- 变量都只在函数作用域内获取,作为函数的参数传入
- 不会产生副作用,不会改变被传入的数据或者其他数据(全局变量)
- 相同的输入保证相同的输出
函数的副作用
副作用指函数被调用,完成函数既定的运算任务,但因为访问了外部数据,尤其是因为对外部数据进行了操作,从而一定程度的改变了系统环境.
内置函数都是纯函数,内置函数一般都是python中的内置类.
常用的内置函数 map函数,会根据提供的函数对指定序列做映射,filter函数,用于过滤序列内置函数三剑客
filter
接收两个参数,源码记述中其本质为一个python类
第一个参数为含有计算规则的函数,第二个为可迭代对象.
案例1
其返回的即是列表li中所有满足fun中小于5的值,且组合成一个新的序列.def fun():
# return true
return n < 5
li =[1,2,3,4,5,6,7,8]
fil = filter(fun,li) # 两个参数,第一个为函数,第二个为可迭代对象
# 执行逻辑,将可迭代对象中的元素遍历传入fun进行计算
print(type(fil)) # 返回为一个filter对象
print(list(fil)) # 可以通过转换成list直接打印出来
map
同filter一样,接收两个参数,直接返回的是一个map对象.
filter会根据返回值判断是否将值放入新的序列中,map则会直接将返回值拿过来,相当于将可迭代对象便利传入func中并取到func运行之后的返回值.
使用场景常常为需要统一处理一批数据的时候.
案例2li_source = [ i for in range(1,20)]
def func(n):
# 写一个生成斐波那契数列的map函数方法
if n==1 or b==2 :
return 1
else :
return func(n-1) + func(n-2)
fib = map(func,li_source)
# 执行逻辑即是,便利li_source将其中元素迭代传入func,按照其内部逻辑执行并返回
zip
主要用来打包数据,接收数据与前两者不同,可以接收多个可迭代对象.
吧第一个可迭代元素遍历与第二个可迭代对象打包成元组.
之后强转为dict可以生成字典. 这种处理方式经常用来操作测试用例数据
长短不一的时候会自动取最短的,舍弃多余项匿名函数
匿名函数一种特殊的函数,不用def去定义,也不用给函数起名字,通过lambda表达式来定义.
这种函数称为匿名函数
写法 :lambda 参数 : 表达式 (返回值)
ex: lambda var : var1 *2
lambda a,b: a+b
前面相当于两个没有函数的参数,冒号后面相当于return,那么如何传参数呢?
匿名函数的适用场景 : 简单的函数定义(只有一个表达式的那种)
我们按照传统函数的思路来写个传参调用,
lamdba a,b : a+b(1,2)
但是匿名函数是不能按照传统参数那样直接在函数后添加()进行调用.
按照上面的写法,会将()中的内容也当作表达式的一部分,并不会被当成是参数
解决方式是(lambda a,b:a+b)(参数1,参数2),通过()将函数体与参数分割开来即可,
匿名函数实战的常规写法,lambda是直接调用,直接使用,用完就丢,释放内存,用变量去保存反而会浪费一块内存去保存.
实例iterator = filter(lambda x: x<10 ,li) # 所以lambda常常和filter,map一起使用,
# 直接使用,用完就丢掉
print(list(iteraotr))
# 列表推导式中也可以使用
li2 = [(lambda x: x % 2==0)(i) for i in range(10)]
# 其执行逻辑是,for循环遍历出i的值为1-10,然后i作为参数传入前面的匿名函数,最终生成值形成新列表
三目运算符
三木运算符,适用于一个条件判断,成立,做A,不成立,做B
python版本的语法支持为
为真的时候的结果 if 判断条件 else 为假的时候的结果 ( 与其他语言不同的地方是没有冒号
写起来会有中写英语的感觉.偏函数
什么是偏函数呢?
python的内置模块functools中提供了很多有用的功能,其中一个就是偏函数 partial
偏函数的作用
当函数的参数个数太多,需要进行简化的时候,使用functools.partial可以创建一个新的函数,这个函数可以固定住原函数的部分参数,从而简化调用时的使用.
在感觉上接近于对函数的在封装,方便进行调用
partial()是不定长参数,可以封装很多东西进去,函数写第一位,后面则是参数位
上实例
li =[1,2,3,4,5,6,7,8,9]
li1 =[1,2,3,4,5,6,7,8,9]
li2 =[1,2,3,4,5,6,7,8,9]
li3 =[1,2,3,4,5,6,7,8,9]
li4 =[1,2,3,4,5,6,7,8,9]
li5 =[1,2,3,4,5,6,7,8,9]
# 有以上这么多列表等待处理.
# 需求为 ,需要过滤掉小于5的元素
filter(lambda x:x<5,li) # 通过filter的方法处理数据,取满足条件的数据组成新的序列
# 但是如此多的列表,如果要写的话会出现很多冗余代码,此时使用偏函数方法就很合适了
from functools import partial
p = partial(filter,lambda x:x<5)
# 之后调用
p(li) # 就可以简单的调用了