Python语言基础6:递归、高阶函数、闭包、装饰器 学习笔记
递归
简单理解就是自己引用自己
# 创建一个变量保存结果
n = 10
for i in range(1,10): #range(n,m)函数包含n,不包含m
n *= i
print(n)
# 创建一个函数,求任意数的阶乘
def fn_recursion(n):
'''
该函数用来求任意数的阶乘
参数:
n 表示所要求阶乘的数
'''
# 创建一个变量,来保存结果
result = n
for i in range(1,n):
result *= i
return result
print(fn_recursion(10))
# 递归式的函数:在函数中自己调用自己
# 无穷递归:如果这个函数被调用,程序的内存就会溢出,效果类似死循环
'''
def fn():
fn()
fn()
'''
'''
递归是解决问题的一种方式,它和循环很像
它的整体思想是:将一个大问题分解为一个个小问题,
直到无法分解时,再去解决问题
递归式函数的两个条件
1 基线条件:问题可以被分解为最小问题,当满足基线条件时,递归就不再执行
2 递归条件:将问题继续分解的条件
递归和循环类似,基本是可以互相代替的
递归要求能看懂即可
10! = 10 * 9!
9! = 9 * 8!
...
2! = 2 * 1!
1! = 1
'''
def factorial(n):
'''
该函数用来求任意数的阶乘
参数:n 表示要求阶乘的数
'''
# 基线条件:判断n 是否为1 ,如果为1 ,则测试不能继续分解
if n == 1:
# 1 的阶乘就是1 ,因此直接返回1
return 1
# 递归条件
return n * factorial(n-1)
print(factorial(10))
# 创建一个函数power 来为任意数字做幂运算 n ** i
def power(n,i):
'''
:param n: 要做幂运算的数字
:param i: 做幂运算的次数
'''
# 基线条件
if i == 1:
# 求 1 次幂
return n
# 递归条件
return n * power(n , i-1)
print(power(5,3))
# 创建一个函数,用来检查一个任意的字符串是否是回文字符串,如果是则返回True,否则返回False
# 回文字符串:正反念都是一样的,eg:abcba
# 先检查第一个字符和最后一个字符是否一致,
# 如果不一致,则不是回文字符串,如果一致,则检查剩下部分
# 检查 abcdedcba 是不是回文
# 检查 bcdedcb 是不是回文
# 检查 cdedc 是不是回文
# 检查 ded 是不是回文
# 检查 e 是不是回文
def hui_wen(s):
'''
该函数用来检查指定的字符串是否是回文字符串,是则返回True,否则返回False
:param s: 要检查的字符串
:return:
'''
# 基线条件
if len(s) < 2 :
# 字符串长度小于2 ,则字符串一定是回文
return True
elif s[0] != s[-1]:
# 第一个字符和最后一个字符不相等,不是回文字符串
return False
# 递归条件
return hui_wen(s[1:-1])
print(hui_wen('abcdcba'))
高阶函数 :
接收函数作为参数,或者将函数作为返回值的函数四高阶函数
当我们使用一个函数作为参数时,实际上是将指定的代码传递进了目标函数
# 创建一个列表
from numpy import sort
l = [1,2,3,4,5,6,7,8,9]
# 定义一个函数,检查一个任意数字是否是偶数
def fn2(i):
if i % 2 == 0:
return True
return False
# 定义一个函数,检查指定的数字是否大于5
def fn3(i):
if i > 5:
return True
return False
# 定义有一个函数
# 可以指定列表中的所有偶数,保存到一个新的列表中返回
def fn(fnc,lst):
'''
fn() 函数可以将指定列表中的所有偶数获取出来,保存到一个新列表中返回
:param lst: 要进行筛选的列表
:return:
'''
# 创建一个新列表
new_list = []
# 对列表进行筛选
for n in lst:
# 判断n 的奇偶
if fn3(n):
new_list.append(n)
# 返回新列表
return new_list
def fn4(i):
if i % 3 == 0:
return True
return False
# print(fn(fn2,l))
# filter() 可以从序列中过滤出符合条件的元素,保存到一个新的序列中
# 参数:
# 1 函数,根据该函数来过滤序列(可迭代的结构)
# 2 需要过滤的序列(可迭代结构)
# 返回值:过滤后的新序列(可迭代的结构)
# fn4 是作为参数传递进filter()函数中
# fn4 实际上只有一个左永刚,就是作为filter()的参数
# filter() 调用完以后,fn4 就已经没用
print(list(filter(fn4,l)))
# 匿名函数 lambda 函数表达方式
# lambda 函数表达式专门用来创建一些简单的函数,是函数创建的另外一种方式
# 语法:lambda 参数列表:返回值
# 一般都是作为参数使用
def fn5(a,b):
return a + b
# print(lambda a,b : a+b)
# 也可以将匿名函数赋值给一个变量,一般不会这么做
fn6 = lambda a,b : a + b
r = filter(lambda i: i>5,l)
print(list(r))
# map() 函数可以对可迭代对象中的所有元素做指定的操作,然后将其添加到一个新的对象中返回
m = map(lambda i: i+1,l)
print(list(m))
# sort() 方法用来对列表中的元素进行排序
# 默认是直接比较列表中的元素大小
# 在sort() 可以接收一个关键参数,key
# key 需要一个函数作为参数,当设置了函数作为参数
# 每次都会以列表中的一个元素作为参数来调用函数,并且使用函数的返回值来比较元素大小
s = ['bb','aaa','c','ddddd','ddd']
# s = sort(key=len)
# print(s)
# sorted() 和sort() 用法基本一致,但是sorted()可以对任意的序列进行排序
# 并且使用sorted() 排序不会影响原来的对象,而是返回一个新对象
sd = [1,3,5,6,'4','7']
print('排序前:',sd)
print('sorted排序:',sorted(sd,key=int))
闭包
将函数作为返回值返回,也是一种高阶函数
这种高阶函数我们也称为闭包,通过闭包可以创建一些只有当前函数可以访问的变量
可以将一些私有的数据藏到闭包中
def fn():
a = 10
# 函数内部定义一个函数
def inner():
print('我是fn2',a)
# 将内部函数 inner作为返回值返回
return inner()
# r 是一个函数,是调用fn()后返回的函数
# 这个函数是在fn() 内部定义,并不是在全局函数
# 所以这个函数总是能访问到fn()函数内的变量
print(fn())
r = fn()
# 求多个数的平均值
nums = [59,4,53,57,85,34]
print(sum(nums)/len(nums))
# 形成闭包的必要条件
# 1 函数嵌套
# 2 将内部函数作为返回值返回
# 3 内部函数必须要使用到外部函数的变量
def make_averager():
# 创建一个列表,用来保存数值
num = []
# 创建一个函数,用来计算平均值
def averager(n):
# 将n 添加到列表中
num.append(n)
# 求平均值
return sum(num)/len(num)
return averager
averager = make_averager()
print(averager(12))
print(averager(14))
装饰器
# 创建几个函数
'''
求任意两个数的和
'''
def add(a , b):
r = a + b
return r
'''
求任意两个数的积
'''
def mul(a , b):
r = a * b
return r
# 希望函数可以在计算前,打印开始计算,计算结束后,打印计算完毕
'''
我们可以直接通过修改函数中的代码来完成这个需求,但是会产生下一个问题
1 如果要修改的函数过多,修改起来会比较麻烦
2 并且不方便后期的维护
3 会违反开闭原则(OCP)
程序的设计,要求开发对程序的扩展(升级),要关闭对程序的修改(修改源代码)
'''
#r = add(123,345)
#print(r)
# 希望不修改原函数的情况下,对原函数进行扩展
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(23,34)
print(r)
# 上面的方式,已经可以在不修改源代码的情况下对函数进行扩展了
# 但是,这种方式要求我们每扩展一个函数就要手动创建一个新的函数,
# 为了解决这个问题,我们需要创建一个函数u,让这个函数㐓自动的帮助我们生产新函数
# 在定义函数时,可以通过@装饰器,来使指定的装饰器来装饰当前的函数
# 理解该函数的逻辑
def begin_end(old):
'''
用来对其他函数进行扩展,是其他函数可以在执行前开始执行,执行后打印执行结束
参数:
old要扩展的函数对象
'''
# 创建一个新函数
def new_function(*args,**kwrgs):
print('开始执行。。。。')
# 调用被扩展的函数
result = old(*args,**kwrgs)
print('执行结束。。。。')
# 返回函数的执行结果
return result
# 返回新函数
return new_function(fn)
# f = begin_end(fn)
# r = f(123,456)
# print(r)
# 向begin_end()这种函数我们称他为装饰器
# 通过装饰器,可以在不修改原来函数的情况下来对函数进行扩展
# 在开发中,我们都是通过装饰器来扩展函数的功能的
#
@begin_end
def say_hello():
print('大家好')
say_hello()