10-函数三
- 1、高阶函数
- 接收函数作为参数,或者将函数作为返回值返回的函数就是高阶函数
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2020/9/9 0009 16:32
# @Author : Oliver
#高阶函数
#有两个特点,符合任意一个特点这个函数就是一个高阶函数
#1.接收一个或多个函数作为参数
#2.将函数作为返回值返回的也是个高阶函数
#当我们使用一个函数作为参数的时候,实际上是将代码传递到了目标函数
lst=[1,2,3,4,5,6,7,8,9,10]
#在函数的内部定义一个函数,用来检测一个任意的偶数
def fn2(i):
if i%2==0:
return True
def fn3(i):
if i>5:
return True
return False
#定义一个函数
#可以指定一个列表,把列表中的偶数保存到一个新的列表
def fn(func,l):
#这个参数l就是被指定的列表
#创建一个新的列表
new_lst=[]
for n in l:
#判断n的奇偶
if func(n):
new_lst.append(n)
return new_lst
print(fn(fn2,lst))#求偶数
print(fn(fn3,lst))#求大于5的
结果显示:
[2, 4, 6, 8, 10]
[6, 7, 8, 9, 10]
Process finished with exit code 0
- 匿名函数
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2020/9/9 0009 16:50
# @Author : Oliver
# filter()就是一个高阶函数,他需要将别的函数作为参数来传递
# 可以将我们的可迭代对象进行一个过滤
#返回值是一个可迭代的对象
lst=[1,2,3,4,5,6,7,8,9,10]
def fn4(i):
if i%3==0:
return True
return False
print(list(filter(fn4,lst)))#求3的倍数
#匿名函数lambda表达式
# lambda表达式是专门用来创建一些简单的函数,他也是函数的另一种创建方式
#语法:lambda 参数列表:返回值
#实现两个数的求和
def fn5(a,b):
return a+b
print(fn5(1,2))
#下面是一个匿名函数
print((lambda a,b:a+b)(10,50))
fn6=(lambda a,b:a+b)(10,50)
print(fn6)
fn7=lambda a,b:a+b
print(fn7(5,6))
#匿名函数最大的好处,他只会用一次,用完之后就会从内存消失
print(list(filter(lambda i:i%3==0,lst)))
#等价于下述代码:(用lambda替代了fn4这个基本函数)
# lst=[1,2,3,4,5,6,7,8,9,10]
# def fn4(i):
# if i%3==0:
# return True
# return False
# print(list(filter(fn4,lst)))
结果显示:
[3, 6, 9]
3
60
60
11
[3, 6, 9]
Process finished with exit code 0
- 2、闭包
- 将函数作为返回值也是高阶函数我们也称为闭包
- 闭包的好处
- 通过闭包可以创建一些只有当前函数能访问的变量
- 可以将一些私有数据藏到闭包中
- 行成闭包的条件
- 函数嵌套
- 将内部函数作为返回值返回
- 内部函数必须要使用到外部函数的变量
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2020/9/9 0009 17:10
# @Author : Oliver
#高阶函数的第二种:将函数作为参数返回的
#这种高阶函数我们称之为闭包
#通过闭包可以创建一些只有当前函数能够访问的变量
#可以将一些私有的数据藏到闭包中
def fn():
a=10
#在函数内部再定义一个函数
def fn2():
print('我是fn2',a)
#将内部函数fn2作为返回值
return fn2
r=fn()
r()
nums=[50,30,10,40,60]
print(sum(nums)/len(nums))
#定义一个函数 用来计算多个数的平均数
def make_fn():
nums=[]#闭包保护了起来
def fn1(n):
#将n添加到列表当中
nums.append(n)
#求平均数
return sum(nums) / len(nums)
return fn1
mf=make_fn()
print(mf(10))
nums=[]
print(mf(20))
#闭包的条件:
#函数嵌套
#内部函数要是用外部函数的变量
#将内部函数作为返回值返回
结果显示:
我是fn2 10
38.0
10.0
15.0
Process finished with exit code 0
- 3、装饰器的引入
- 我们可以直接通过修改函数中的代码来完成需求,但是会产生以下一些问题
- 如果修改的函数多,修改起来会比较麻烦
- 不方便后期的维护
- 这样做会违反开闭原则(ocp)
- 程序的设计,要求开发对程序的扩展,要关闭对程序的修改
- 我们可以直接通过修改函数中的代码来完成需求,但是会产生以下一些问题
- 4、装饰器的使用
- 通过装饰器,可以在不修改原来函数的情况下来对函数进行扩展
- 在开发中,我们都是通过装饰器来扩展函数的功能的
- @函数名的方式来对其他的函数进行扩展
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2020/9/9 0009 19:02
# @Author : Oliver
def add(a,b):
#求两个数的和
print('函数开始执行')
r=a+b
print('函数执行结束')
return r
def mul(a,b):
#求两个数的乘积
return a*b
r=add(1,2)
print(r)
#我们可以直接铜鼓修改函数的方式来完成这个需求
#但是会产生一些问题
#1.如果修改的函数过多,修改起来就会比较的麻烦
#2.后期维护不方便
#3.这样做会违反一个OCP原则(开闭原则)就是要求开放对程序的扩展,要求关闭对程序的修改
#我希望扩展fn函数,但是要求不修改原函数的情况相爱对他进行扩展
def fn():
print('我是fn函数')
#定义一个新的函数,就是对原函数进行的扩展
def fn2():
print('函数开始执行')
fn()
print('函数执行结束')
fn2()
def new_add(a,b):
print('函数开始执行')
r=add(a,b)
print('函数执行结束')
return r
r=new_add(1,2)
print(r)
#发现我们只能定义新的函数对原函数进行扩展,但是这样做的话,
#要是扩展的比较多,就要不断的定新的函数
#我们想的是如果一个函数能够统一扩展很多的函数是不是就比较的好呢
#这就是装饰器了
#接下来我们看一下装饰器的使用
print()
print()
def fn6():
print('我是fn6函数')
#定义一个函数,就是对其他函数进行扩展的,扩展的功能一个是打印函数爱是执行 一个是打印函数执行结束
def start_end(old):
#内部创建了一个函数
def new_function():
print('函数开始执行')
old()
print('函数执行结束')
#返回一个新的函数
return new_function
f=start_end(fn6)
# f2=start_end()
print(f())
# print(f2)
#像类似于start_end(old)这种函数我们称之为装饰器
#通过装饰器可以在不修改原来的函数的情况下对函数进行扩展
# 在开发中,,我们都是通过装饰器来扩展函数的功能
@start_end
def speak():
print('大家真的不容易啊')
#speak被装饰器装饰了
speak()
结果显示:
函数开始执行
函数执行结束
3
函数开始执行
我是fn函数
函数执行结束
函数开始执行
函数开始执行
函数执行结束
函数执行结束
3
函数开始执行
我是fn6函数
函数执行结束
None
函数开始执行
大家真的不容易啊
函数执行结束
Process finished with exit code 0
- 课程作业
- 判断回文字符串
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2020/9/9 0009 19:43
# @Author : Oliver
#采用递归的思想解决回文字符串的判断
def fn(s):
#1.基线条件
#如果字符串的长度小于2,则字符串是回文字符串
if len(s)<2:
return True
#先检查第一个字符和最后一个字符是否一致,如果不一致则不是回文
elif s[0]!=s[-1]:
return False
#2.递归条件 abcba
return fn(s[1:-1])
print(fn('abc'))
print(fn('cbc'))