函数式编程
'''
函数式编程
在Python 中,函数也是一等对象(Java 8 中函数才成为一等对象)
一等对象的特点:
1. 对象是在运行时期创建的
2. 可以赋值给变量作为数据结构中的元素
3. 可以作为参数传递
4. 可以作为返回值
函数式编程中的高阶函数至少要满足以下条件之一:
1. 接收一个或者多个函数作为参数
2. 返回值为函数类型
'''
# 练习
old_list = [1, 34, 2, 45, 23, 43, 26]
# 定义一个函数,判断数字是否是偶数
def judge_num1(num: int)->bool:
return num % 2 == 0
# 定义一个函数,判断数字是否大于10
def judge_num2(num: int)->bool:
return num > 10
def super_func(old_list: list, func)->list:
new_list = []
for i in old_list:
if func(i):
new_list.append(i)
return new_list
# print(super_func(old_list, judge_num1)) # [34, 2, 26]
# print(super_func(old_list, judge_num2)) # [34, 45, 23, 43, 26]
匿名函数(lambda 表达式)以及内置函数filter,map,sorted和sort 方法
# filter()
# filter()可以从序列中过滤出符合条件的元素,保存到一个新的序列中
# 参数:
# 1.函数,根据该函数来过滤可迭代对象
# 2.需要过滤的可迭代对象
# 返回值:
# 过滤后的可迭代对象(通过list()方法转换为列表数据类型)
print(list(filter(judge_num1, old_list))) # [34, 2, 26]
# 匿名函数 lambda 函数表达式 (语法糖)
# lambda函数表达式专门用来创建一些简单的函数,他是函数创建的又一种方式
# 语法:lambda 参数列表 : 返回值(这里可以通过调用其他函数,或者直接写简单的处理代码)
# 匿名函数一般都是作为参数使用,其他地方一般不会使用
print(list(filter(lambda num: num > 10, old_list))) # [34, 45, 23, 43, 26]
print(list(filter(lambda num: judge_num1(num), old_list))) # [34, 2, 26]
# map()函数:映射,对可迭代对象中每个元素做指定操作,并返回新的元素组成的迭代对象
# [101, 134, 102, 145, 123, 143, 126]
print(list(map(lambda num: num + 100, old_list)))
# sort()
# 该方法用来对列表中的元素进行排序,直接操作原列表,没有返回值
# sort()方法默认是直接比较列表中的元素的大小
# 在sort()可以接收一个关键字参数 , key
# key需要一个函数作为参数,当设置了函数作为参数
# 每次都会以列表中的一个元素作为参数来调用函数,并且使用函数的返回值来比较元素的大小
old_list.sort()
print(old_list) # [1, 2, 23, 26, 34, 43, 45]
old_list = ['cris', '1234', 'a', 'james']
old_list.sort(key=len)
print(old_list) # ['a', 'cris', '1234', 'james']
old_list = [1, '11', 23, 2, '0']
old_list.sort(key=int)
print(old_list) # ['0', 1, 2, '11', 23],改变原列表的排序,不会改变元素的数据类型
# sorted()
# 这个函数和sort()的用法基本一致,但是sorted()可以对任意的序列进行排序
# 并且使用sorted()排序不会影响原来的对象,而是返回一个新对象
names = (1, 4, 12, 0)
a = sorted(names)
print(a) # [0, 1, 4, 12] 返回新列表
print(names) # (1, 4, 12, 0) 原序列不变
闭包
# 将函数作为返回值返回,也是一种高阶函数
# 这种高阶函数我们也称为叫做闭包,通过闭包可以创建一些只有当前函数能访问的变量
# 可以将一些私有的数据藏到的闭包中,防止我们定义的变量被修改或者覆盖
# 如果我们想要定义一个函数用于计算平均值,用于不断的往列表中添加元素并计算,以下方式是很危险的
nums = []
def func(a: float)->float:
nums.append(a)
return sum(nums) / len(nums)
print(func(10)) # 10.0
print(func(30)) # 20.0
# nums = [100]
print(func(50)) # 30.0
# 形成闭包的要件
# ① 函数嵌套(外部函数里面必须有内部函数)
# ② 将内部函数作为返回值返回
# ③ 内部函数必须要使用到外部函数的变量
# 以下闭包可以保护数据(nums)的安全,因为作用域的存在,对外部函数以外的范围不可见
def clouser_func():
nums = []
def func(num: int):
nums.append(num)
return sum(nums) / len(nums)
return func
close_func = clouser_func()
print(close_func(22)) # 22.0
print(close_func(26)) # 24.0
装饰器
# 装饰器,类似Java 的动态代理,但是使用更加方便,可以对原有的函数进行扩展
# 示例如下:
def add(a: float, b: float)->float:
return a + b
def sub(a: float, b: float, c: float)->float:
return a - b - c
def decoration_func(fn):
def new_func(*args, **kwargs):
print('函数开始执行')
result = fn(*args, **kwargs)
print('函数执行完毕')
return result
return new_func
new_func = decoration_func(add)
print(new_func(1, 5)) # 6
print(decoration_func(sub)(1, 2, 3)) # -4
# Python 中的装饰器用法,使用 @装饰器函数 的方式为想要扩展的函数提供最简单的写法,此时再去调用原函数已经是装饰过后的函数了
# 可以同时为一个函数指定多个装饰器,这样函数将会按照从内向外的顺序被装饰
@decoration_func
def hello():
print('hello,Cris')
hello()