Python函数式编程

函数式编程基础

函数式编程与面向对象编程一样都是一种编程范式,函数式编程也称为面向函数的编程。Python提供了高阶函数、函数类型和lambda表达式,他们是实现函数式编程的基础。

高阶函数与函数类型

如果一个函数可以作为其他函数的参数或者其他函数的返回值,那么这个函数就是“高阶函数”。任何一个函数的数据类型都是 function 类型,即“函数类型”。

 示例代码如下

def calculate_fun():
    def add(a,b):   #重构了 calculate_fun() 函数
        return a+b
    return add      #返回嵌套函数 add
f = calculate_fun() #将变量f指向 add 函数
print(type(f))
print("10 + 5 = {0}".format(f(10,5)))

代码运行结果

<class 'function'>
10 + 5 = 15

 函数作为其他函数返回值使用

可以把函数作为其他函数的返回值使用,下面举个栗子:定义了两个嵌套函数add() 和sub() ,根据参数返回不同的函数

示例代码如下

def calculate_fun(opr):
    def add(a,b):   #定义相加函数
        return a+b
    def sub(a,b):   #定义相减函数
        return a-b
    if opr == '+':
        return add
    else:
        return sub
f1 = calculate_fun('+') #将变量f指向 add 函数
f2 = calculate_fun('-')
print("6 + 12 = {0}".format(f1(6,12)))
print("12 - 6 = {0}".format(f2(12,6)))

代码运行结果

6 + 12 = 18
12 - 6 = 6

函数作为其他函数参数使用

 示例代码如下

def calculate_a(value, op):     #定义了一个函数,其中 value 是要计算的操作数,op参数是一个函数
    return op(value)
def square(n):
    return n*n
def abs(n):
    return n if n > 0 else -n
print("6的平方 = {0}".format(calculate_a(6,square)))
print("-6的绝对值 = {0}".format(calculate_a(-6,abs)))

代码运行结果

6的平方 = 36
-6的绝对值 = 6

匿名函数与lambda表达式

“匿名函数”即在使用的时候不给函数分配名字,在 Python 中用 lambda 表达式表示匿名函数,lambda 是关键字声明(表示这是 lambda 表达式),“参数列表”与函数参数列表相同,但不需要小括号括起来,冒号后面是“lambda体”,类似于函数体。

声明 lambda 表达式的语法如下:

lambda 参数列表: lambda体

注意: lambda体 部分不能是一个代码块,不能包含多条语句,只能有一条语句,语句会计算一个结果返回给 lambda 表达式,但是与函数不同的是,不需要使用 return 语句返回。与其他语言(如Java)中的 lambda 表达式相比,Python中的 lambda 表达式只能提供一些简单的运算。 

示例代码如下

def calculate_a(opr):
    if opr=='+':
        return lambda a,b:(a+b) #替代了add函数,简化代码
    else:
        return lambda a,b:(a-b) #替代了sub函数,简化代码
f1 = calculate_a('+')
f2 = calculate_a('-')
print(type(f1))
print("6 + 6 = {0}".format(f1(6,6)))
print("6 - 6 = {0}".format(f2(6,6)))

代码运行结果

<class 'function'>
6 + 6 = 12
6 - 6 = 0
案例二:加深对匿名函数的使用

示例代码如下

list1 = [1,2,3,4,5,6]
for i in range(len(list1)):
    result = lambda x:x[i] # 此处x为形参
    print(result(list1)) # 此处list1为实参

print('-'*30)
# 此外,还可以使用匿名函数来排序
list2 = [
    {'name':'people1','score':100},
    {'name':'people2','score':80},
    {'name':'people3','score':60},
    {'name':'people4','score':90}
]
# 排序规则为按照score降序排序
list2.sort(key=lambda x:x.get('score'),reverse=True)
print(list2)

代码运行结果

1
2
3
4
5
6
------------------------------
[{'name': 'people1', 'score': 100}, {'name': 'people4', 'score': 90}, {'name': 'people2', 'score': 80}, {'name': 'people3', 'score': 60}]

Process finished with exit code 0

递归函数

在一个函数的函数体内调用该函数本身,该函数就是递归函数。其中递归由两部分组成:递归调用和递归终止条件。 其优点为代码编写时比较简单,缺点为代码运行时所占用的内存比较多。

示例代码如下

# 使用递归计算n的阶乘
def calculate_factorial(num1):
    if num1 == 1:
        return 1
    else:
        return num1*calculate_factorial(num1-1)
result = calculate_factorial(6)
print(result)

# 使用递归完成斐波那契数列:1,1,2,3,5,8,13...
print('-'*30)
def calculate_fibo(num1):
    if num1 == 1 or num1 == 2:
        return 1
    else:
        return calculate_fibo(num1-1)+calculate_fibo(num1-2)
result_5 = calculate_fibo(5)
print(f'斐波那契数列中在位置为5的数字为:{result_5}')
# 打印该数列中前15个数字
for i in range(1,15):
    print(calculate_fibo(i),end='\t')
print('\n')

代码运行结果

720
------------------------------
斐波那契数列中在位置为5的数字为:5
1	1	2	3	5	8	13	21	34	55	89	144	233	377	


Process finished with exit code 0

函数式编程的三大基础函数 

过滤(filter)、映射(map)、聚合(reduce)是处理数据的三大基本操作

过滤函数filter()

可以对可迭代对象的元素进行过滤,filter() 函数语法如下:

filter(function,iterable)

其中 function 是一个函数,参数 iterable 是可迭代对象。在filter函数调用时,iterable 会被遍历,它的元素会被逐一传入 function 函数,function函数 返回布尔值。在 function函数 中编写过滤条件,结果为True 的元素会被保留,结果为 False 的函数会被过滤掉。

示例代码如下

users = ['Tony','Tom','jack','Tome']
users_filter = filter(lambda u:u.startswith('T'),users)
# 过滤条件为T开头的元素,lambda u:u.startswith('T')是一个lambda表达式
# filter函数不是列表,需要使用list函数转化为列表
print(list(users_filter))

print("示例2:")
'''下面示例实现了获取1~20中能被3整除的数'''
number_list = range(1,21)
number_filter =  filter(lambda it:it % 3 == 0,number_list)
print(list(number_filter))

代码运行结果 

['Tony', 'Tom', 'Tome']
示例2:
[3, 6, 9, 12, 15, 18]

映射函数map()

 可以对可迭代对象的元素进行变换,map()函数语法如下:

map(function,iterable)

示例代码如下

users = ['Tony','Tom','jack','Tome']
users_map = map(lambda u:u.lower(),users)
print(list(users_map))

print("使用过滤器和map的示例2:")
'''
函数式编程时数据可从一个函数流入另外一个函数,但遗憾的是Python并不支持“链式”API
因此在实现“获取T开头的字母,再将其转换为小写字母”这样的需求时
需要使用filter函数进行过滤再用map进行映射变换
'''
users = ['Tony','Tom','jack','Tome']
users_filter = filter(lambda u:u.startswith('T'),users)
users_map = map(lambda u:u.lower(),users_filter)
# users_map = map(lambda u:u.lower(),filter(lambda u:u.startswith('T'),users))
# 该段代码实现和上面一样的效果,但是可读性则不是很好
print(list(users_map))

代码运行结果

['tony', 'tom', 'jack', 'tome']
使用过滤器和map的示例2:
['tony', 'tom', 'tome']

聚合函数reduce()

聚合操作会将多个数据聚合起来输出单个数据,reduce()函数会将多个数据按照指定的算法积累叠加起来,最后输出一个数据,reduce()函数语法如下:

reduce(function,iterable[,initializer])

参数 function 是聚合操作函数,iterable 是可迭代对象, initializer 是初始值,接下来通过一个示例实现对一个数列的求和运算

示例代码如下

from functools import reduce
#导入functools模块,因为reduce是在functools模块中定义的
a = (3,4,5,6)
a_reduce = reduce(lambda acc,i:acc+i ,a)
print(a_reduce)
b = (3,4,5,6)
b_reduce = reduce(lambda acc,i:acc+i ,b,2)
print(b_reduce)

代码运行结果

18
20

装饰器

装饰器是一种设计模式,就是在不修改函数代码的情况下,给函数增加一些功能

使用装饰器

Python提供了装饰器注释功能,使用  @方法名 装饰器声明。一个函数可以有多个装饰器声明。

示例代码如下

def uppercase_decorator(func):
    def inner():
        s = func()# 调用原始函数
        make_uppercase = s.upper()# 将结果转换为大写
        return make_uppercase
    return inner
def bracket_decorator(func):
    def inner():
        s = func()# 调用原始函数
        make_bracket = '['+s+']'# 将结果前后加上方括号
        return make_bracket
    return inner
#使用装饰器装饰 say_hello 函数
@bracket_decorator
@uppercase_decorator
def say_hello():
    return 'hello world.'
print(say_hello())

say_hello 函数首先被 uppercase_decorator 装饰,然后是 bracket_decorator。这意味着 say_hello 函数被 uppercase_decorator 包裹,返回的函数再被 bracket_decorator 包裹。

  • say_hello() 调用 bracket_decorator 的 inner 函数。
  • 这个 inner 函数再调用 uppercase_decorator 的 inner 函数。
  • 最后,uppercase_decorator 的 inner 函数调用原始的 say_hello 函数,获取字符串 'hello world.',转换为大写,然后返回给 bracket_decorator 的 inner 函数。
  • bracket_decorator 的 inner 函数将结果加上方括号,然后返回

代码运行结果

[HELLO WORLD.]

给装饰器传递参数

装饰器本质上是一个函数,因此可以给装饰器传递参数

示例代码如下

def calc(func): # 它的参数还是一个函数
    def wrapper(arg1): #定义嵌套函数,其参数列表(arg1)与装饰器要注释的函数参数列表一致
        return func(arg1)

    return wrapper
@calc
def square(n):
    return n*n

@calc
def abs(n):
    return n if n>0 else -n
print("6的平方 = {0}".format(square(6)))
print("-6的绝对值 = {0}".format(abs(-6)))

代码运行结果

6的平方 = 36
-6的绝对值 = 6
  • 25
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

邂逅自己

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值