Python 函数式编程 内置高阶函数及周边【进阶篇 3】推荐

前面我们已经总结并实践了用python获取到了数据。也介绍了python中http网络请求的几种方式,正在学习python开发语言或者对python3知识点生疏需要回顾的请点这里 ,本章主要总结了函数式编程及特点 和 python中内置的高阶函数及周边知识,方便自己查看也欢迎大家参考,谢谢。

目录

一、了解函数式编程

二、python内置的高阶函数及周边

1.把函数当作参数

2.Python的内置函数map()

3.Python的内置函数reduce()

4.python的内置函数filter() 

5.Python排序函数 sorted()

6.Python返回函数

7.Python的闭包 

8.Python的匿名函数

9.Python编写无参数的decorator 

10.Python编写有参数的decorator

11.Python的偏函数

三、总结

 【python 入门篇 1 2 3 】


一、了解函数式编程

函数式编程的特点:

  1. 不是纯函数式编程:允许有变量
  2. 支持高阶函数:函数可以作为变量
  3. 支持闭包:可以返回函数
  4. 支持匿名函数

二、python内置的高阶函数及周边

1.把函数当作参数

顾名思义就是把一个函数当作参数使用。例如:

# abs函数把传递的数据乘以10 后返回 
def abs(x):
    return x*10

# 这里参数 f参数就是需要传递一个函数
def add(x, y, f):
    return f(x) + f(y)

# 这里在调用add方法的时候 把上面abs函数作为参数传入
result =  add(-5, 9, abs) 

# 相当于 result = abs(-5) + abs(9) 
print(result)  # 40
2.Python的内置函数map()

map()是 Python 内置的高阶函数,它接收一个函数 f 和一个 list。并通过函数 f处理list中的每个元素,map()函数会返回一个迭代器,可以依次迭代得到原来list的元素被函数f处理后的结果。

例如,对于list [9, 8, 7, 6, 5, 4, 3, 2, 1]。
如果希望把list的每个元素都作平方,就可以利用map()函数。

 

3.Python的内置函数reduce()

reduce()函数接收的参数和 map() 类似,一个函数 f,一个list,但行为和 map()不同,reduce()传入的函数 f 必须接收两个参数,reduce()对list的每个元素反复调用函数f,并返回最终结果值。

在python3中,reduce()函数被收录到functools包内,需要引入functools才可以使用。

# 从functools包中引入reduce模块
from functools import reduce
# 定义一个list数组
list = [5, 4, 3, 2, 1]
# 定义当做reduce函数的参数的函数
def f(x,y):
    return x*y

# 执行reduce高阶函数后打印数据
print(reduce(f, list))

其实这个计算结果是120. 其实就是list元素的乘积 5*4*3*2*1 = 120.

f(5,4)  f(20,3) f(60,2) f(120,1) 就是f()函数第一次执行的结果当做下一次函数的x参数使用,返回最终结果。

reduce()还可以接收第3个可选参数,作为计算的初始值。如果把初始值设为2

# 执行reduce高阶函数后打印数据
print(reduce(f, list, 200))   #24000

 

4.python的内置函数filter() 

filter()函数是 Python 内置的另一个有用的高阶函数,filter()函数接收一个函数 f 和一个list,这个函数 f 的作用是对每个元素进行判断,返回 True或 False,filter()根据判断结果自动过滤掉不符合条件的元素,并返回一个迭代器,可以迭代出所有符合条件的元素。

 例如现在要找出10以内的奇数。

利用filter函数还可以处理空的字符串和无效数据:

 

# 定义要处理的数据
list = ['STR', None, '', 'rose', '  ', 'fly']
# 判断元素是否为空 为空则返回false 执行filter函数会过滤掉
def is_not_empty(s):
    return s and len(s.strip()) > 0
   
# 过滤掉为空的数据并打印数据
for item in filter(is_not_empty, list):
    print(item)

注意: s.strip()会默认删除空白字符(包括'\n', '\r', '\t', ' ')

  

5.Python排序函数 sorted()

Python内置的 sorted()函数可对list进行排序:

  1. 默认是由小到大排序列表的元素。
  2. 当list的每一个元素又是一个容器时,则会以第一个元素来排序 sorted()函数则按名字首字母进行了排序并返回。

如果需要按照成绩高低进行排序,需要指定排序的字段是成绩,sorted接受key参数,用来指定排序的字段,key的值是一个函数,接受待排序列表的元素作为参数,并返回对应需要排序的字段。因此,sorted()函数也是高阶函数。可接收三个参数:

print(sorted(food))      # 经过sorted函数默认排序后打印   

print(sorted(food, key=k))     #传入指定按成绩排序的参数 key

print(sorted(food, key=k,reverse=True))   #reverse 设置倒序排序

6.Python返回函数

在函数内部,是可以定义子函数的。作为高阶函数,可以接受函数作为参数,其实高阶函数,除了不仅仅可以返回int、str、list、dict等数据类型,还可以返回函数。因此,可以把函数的子函数返回。

要注意的是,返回函数和返回函数值的语句是非常类似的,返回函数时,不能带小括号,而返回函数值时,则需要带上小括号以调用函数。 

# 返回函数
def myabs():
    return abs

# 返回函数值
def myabs(x):
    return abs(x)

 返回函数有很多应用,比如可以将一些计算延迟执行:

#直接计算返回list元素求和数据
# 定义函数 返回内置函数 sum()
def calc_sum(list_):
    return sum(list_)

#调用函数得到list数组元素之和赋值给result
result = calc_sum([1, 2, 3, 4])
print(result)  #10

如果返回一个函数,我们必须重新调用返回的函数才会执行内置函数sum,代码应该更清晰。

 这样我们拿到的函数可以根据当前需求决定要不要执行,代码更灵活。

7.Python的闭包 

内层函数引用了外层函数的变量(参数也算变量),然后返回内层函数的情况,称为闭包(Closure)。前面我们用到的例子:calc_sum(list)函数

我们没法把 lazy_sum 移到 calc_sum 的外部,因为它引用了 calc_sum 的参数 list_,像这样内层函数引用外层函数的变量(参数),然后把内层函数返回,就称为闭包。

def calc_sum(list_):
    def lazy_sum():
        return sum(list_)
    return lazy_sum

闭包的特点是返回的函数还引用了外层函数的局部变量,所以,要正确使用闭包,就要确保引用的局部变量在函数返回后不能变。因此,返回函数不要引用任何循环变量,或者后续会发生变化的变量。

8.Python的匿名函数

高阶函数可以接收函数做参数,有些时候,我们不需要显式地定义函数,直接传入匿名函数更方便。

匿名函数使用lambda定义:lambda x: x * x,就可以完成原来显式定义的f(x)函数的功能,冒号前面的x表示匿名函数的参数,后面的是一个表达式,匿名函数有个限制,就是只能有一个表达式,不写return,返回值就是该表达式的结果。

list数组经map函数处理后返回的数据。 

9.Python编写无参数的decorator 

Python的 decorator 本质上就是一个高阶函数,它接收一个函数作为参数,然后,返回一个新函数。

使用 decorator 用Python提供的 @ 语法,这样可以避免手动编写 f = decorate(f) 这样的代码。

编写@log:

def log(f):
    def fn(x):
        print('call ' + f.__name__ + '()...')
        return f(x)
    return fn


#用于阶乘函数
@log
def factorial(n):
    return reduce(lambda x,y: x*y, range(1, n+1))

print(factorial(10))

多个参数时:对于参数大于等于两个的就会报错, @log 写死了只含一个参数的返回函数。要让 @log 自适应任何参数定义的函数,可以利用Python的 args 和 *kwargs,保证任意个数的参数总是能正常调用:

def log(f):
    def fn(*args, **kwargs):
        print('call ' + f.__name__ + '()...')
        return f(*args, **kwargs)
    return fn
10.Python编写有参数的decorator

前面  编写 log函数时 默认打印信息print('call ' + f.__name__ + '()...')语句是固定不变的,只有函数名称可以动态打印,如果我们根据函数的重要做了区分想显示出来怎么办呢?这时,log函数本身就需要传入'INFO'或'DEBUG'这样的参数。

@log('DEBUG')
def my_func():
    pass

#上面的定义翻译成高阶函数的调用
my_func = log('DEBUG')(my_func)

# 又相当于
log_decorator = log('DEBUG')
@log_decorator
def my_func():
    pass

所以,带参数的log函数首先返回一个decorator函数,再让这个decorator函数接收my_func并返回新函数,相当于是在原有的二层嵌套里面,增加了一层嵌套:

def log(prefix):
    def log_decorator(f):
        def wrapper(*args, **kw):
            print('[{}] {}()...'.format(prefix, f.__name__))
            return f(*args, **kw)
        return wrapper
    return log_decorator

@log('DEBUG')
def test():
    pass
test()
11.Python的偏函数

当一个函数有很多参数时,调用者就需要提供多个参数。如果减少参数个数,就可以简化调用者的负担。

偏函数指的就是“创建一个调用另外一个部分参数或变量已经预置的函数”的函数的用法,functools.partial就是帮助我们创建一个偏函数的,不需要我们自己定义。

 int()函数将字符串转换成整数,下面代码int默认是按照十进制去转换的.即默认参数为10,如果传入base参数,就可以做 N 进制的转换:

# int()函数将字符串转换成整数
age1 = int('20',base=10)  
age2 = int('20')

print(age1,age2)  #20 20

# 按照二进制转换
age3 = int('10',base=2)
print(age3)  # 2

 我们可以定义一个int2()的函数,默认把base=2传进去:int2实际上就变成了部分参数(base)已经预置了的偏函数。

def int2(x, base=2):
    return int(x, base)
print(int2('10'))   # 2

functools.partial就是帮助我们创建一个偏函数的,不需要我们自己定义int2(),可以直接使用下面的代码创建一个新的函数int2:

所以,functools.partial可以把一个参数多的函数变成一个参数少的新函数,少的参数需要在创建时指定默认值,这样,新函数调用的难度就降低了。

三、总结

本文主要介绍了函数式编程及特点 和 python中内置的高阶函数及周边: 

1.函数式编程的主要特点:允许有变量函数可以作为变量可以返回函数支持匿名函数

2.python中的内置函数:map()reduce()filter()sorted()闭包匿名函数偏函数等内容。

有问题欢迎大家评论区留言探讨,谢谢。

 另附:python中http请求及网络爬虫获取数据:

1.Python 爬数据案例 客户端服务端http请求 推荐 【进阶篇 2 】-CSDN博客

2.python面向对象继承多态和一些特殊方法的使用

 【python 入门篇 1 2 3 】

1.安装下载基本数据类型:Python 3 入门基础知识【1】数据类型 安装下载 推荐-CSDN博客

2.list数组定义及操作:Python 3 入门基础知识 之数据容器及用法【2】 推荐-CSDN博客

3.函数及参数:Python 3 入门基础知识【3】递归函数以及参数部分-CSDN博客

  • 10
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值