6_python 高阶函数_装饰器


函数式编程和 高阶函数

# 函数式编程和 高阶函数
# 高阶函数
1. 变量可以指向函数本身
2. 函数名 也是变量
# 示例
# 求-10  的绝对值
print(abs(-10))
print(abs)
# abs 是指向一个函数,也就是函数本身 
# abs () 指的是对函数的调用

f=abs # f 变量也是指向abs 所指向 的函数
f(-10) # 可以通过该 变量来调用这个函数 

# 结论: 变量 f 指向了 abs 函数本身

# 函数名 也是变量
# 函数名 其实就是指向函数的变量,  对于abs(0 )这个函数 ,我们可以
# 把函数名 abs 看成是 一个变量,  他指向计算绝对值的函数

abs=10 
print(abs(-10))#这 样就会抛出异常
# 实际使用中 变量 名 命名 是不能这样写的,是为了 说明函数名 也是一个变量


既然变量可以指向函数,函数的参数 能接收变量,那么一个函数就可以接收另外一个函数 作为参数, 这种函数就称之为 高阶函数

# 简单示例  高阶函数
def add (x,y,f):
    return f(x)+f(y)

print(add(-110,5,abs))
# 这样的话 就是 一个 高阶函数的使用
# 函数式编程
'把函数作为参数传入', 这样的函数称为高阶函数, '函数式编程'就是指这种高度抽象的编程范式。

 Python 内建的高阶函数有 mapreducefiltersorted

map

map  函数
map()函数接收两个参数, 一个是函数, 一个是序列, 

map 将传入的函数依次作用到序列的每个元素, 并把结果作为新的 list 返回。实际上是一个 map 对象

也就是映射

# map 函数示例
#  传递两个列表
'''
 map(func, *iterables) --> map object

    Make an iterator that computes the function using arguments from
    each of the iterables.  Stops when the shortest iterable is exhausted.
'''
a=[1,2,3,4]
b=[10,20,30]
def f(x,y):
    return x+y
L=map(f,a,b)
print(list(L))
# 判断是否是可迭代对象
from collections import Iterator
print('判断是否是可迭代的:',isinstance(L,Iterator))
# python 内置函数教程  菜鸟教程
# https://www.runoob.com/python/python-built-in-functions.html
# 传统的实现方法
def g(x):
    return x * x


result_list = []
for i in a:
    result_list.append(g(i))
print(result_list)
# map 的实现方式
a = [1, 2, 3, 4, 5, 6, 7, 8, 9]
def g(x):
    return x * x

def map_(func,a):
	return (func(i) for i in a)
	
c = list(map_(g, a))
print(c)

运行结果

在这里插入图片描述


# 将列表中的 每个元素 转换成字符串
'''
 map(func, *iterables) --> map object

    Make an iterator that computes the function using arguments from
    each of the iterables.  Stops when the shortest iterable is exhausted.
'''
a = [1, 2, 3, 4, 5, 6, 7, 8, 9]  #将列表中每个元素转换为字符串
L = map(str, a)
print(list(L))

reduce

reduce 函数

把一个函数作用在一个序列[x1, x2, x3...]上, 这个函数必须接收两个参数, 

reduce 把结果继续和序列的下一个元素做累积计算, 
其效果就是:
reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)

# reduce 的实现

def reduce_(func,a,init=None):
    if init is None:
        tmp_a=a
    else:
        tmp_a=[init,*a]
        
    pre_cur=[]
    while len(tmp_a)>1:
        pre_cur=tmp_a[:2] 
        tmp_a=tmp_a[1:]
        tmp_a[0]=func(pre_cur[0],pre_cur[1])
    return tmp_a[0]
def foo(x,y):
    return x+y

a=[1,2,3,4,5,6,7,8,9,10]    
sum_=reduce_(foo,a,)

[in] : sum_ 
[out] : 55---------------------------

a=[1,2,3,4,5,6,7,8,9,10]    
sum_=reduce_(foo,a,10)
# 当然这种 高阶函数中简单的函数  可以用 lambda 函数代替。
# reduce_(lambda x,y:x+y,a,10) 
# 10 是初始值。 如果设置了 那么 x 就是 10 
# 没有设置的话 。 x 是  a[0]  y是 a[1]
# 然后计算后返回值 作为 x 下一个元素。 作为 a[1]
# reduce_ 也可以使用递归来实现
# 有兴趣的 可以自己写着 玩。  
 [in]: sum_
 [out]: 65
# 高阶函数 reduce
from functools import reduce
# 计算一个序列的求和
a=[1,2,3,4,5,6,7,8,9,10]
# 普通方法
sum_=0
for i in a:
    sum_+=i
print('累加和:',sum)


# reduce 方法
def sumTest(x,y):
    return x+y
sum=reduce(sumTest,a)
print('reduce计算列表求和:',sum)

# 当然纯粹的 求和的话 sum(a)  就好了
# reduce 的使用方法
from functools import reduce
# 把序列[1, 3, 5, 7, 9]变换成整数13579。将列表中的每个元素乘以10加上后一个元素。
a=[1, 3, 5, 7, 9]
def fun(x,y):
    return x*10+y
result=reduce(fun,a)
print(result)

# 当然以解决问题的想法的话
int(''.join(map(str,a))) # 这个更加符合我们的需求


初始化参数

类似于这种 循环的时候 需要 创建 中间变量的都可以使用 这个 可选的 initial参数。

来使用 reduce 完成 常见的循环操作。

a_string='i like python, javascript, go'

b_li=['python', 'javascript', 'go']

reduce(lambda pre,next_:pre.replace(next_,f"<a>{next_}</a>"),b_li,a_string)
     
     # b_li 就是我们传递进去的 序列。
     # a_string 是我们的默认值 初始化参数


运行结果

在这里插入图片描述


filter

# fileter 的使用

Python 内建的 filter()函数用于过滤序列。 和 map()类似, filter()也接收一个函数和一个序列。 

和 map()不同的时, filter()把传入的函数依次作用于每个元素,

 然后根据返回值是 True  还是 False 决定保留还是丢弃该元素。

一般都是 返回 True 的值
# filter 函数
# 在一个列表中,删掉偶数,保留奇数
def is_odd(n):
    # 求奇数 的函数
    # if n%2==0:
    #     return False
    # else:
    #     return True
    return n%2 == 1  # 这种写法比较  好
L=filter(is_odd,[1,2,3,4,5,6,7,8,9,10])
print(list(L))

#一个序列中的空字符串删掉
a=['A', '', 'B', None, 'C', '  ']
def not_empty(s):
    return s and s.strip()
L=filter(not_empty,a)
print(list(L))

# 我们自己实现 一下 filter
a=['A', '', 'B', None, 'C', '  ']

def filter_(func,seq):
    return [value for value in seq if func(value)]
    # 不同的是 我们返回的是 列表
    # python 自带的 filter 返回的是一个类似于生成器对象的 东西
    # 实现 懒加载。 可以尝试对 filter 使用 next 函数。

def not_empty(s):
    return s and s.strip()


filter_(not_empty,a)

运行结果

在这里插入图片描述
在这里插入图片描述

sorted

sorted  函数
排序算法, 排序也是在程序中经常用到的算法。

 无论使用'冒泡排序'还是 '快速排序', 排序的核心是'比较两个元素 ''大小'。
 
  如果是数字, 我们可以直接比较, 但如果是'字符串'或者两个 dict 呢?

 直接比较数学上的大小是没有意义的, 因此, 比较的过程必须通过函数抽象出来。

通常规定, 对于两个元素 x 和 y, 如果认为 x < y, 则返回-1, 如果认为 x == y, 

则返回 0,如果认为 x > y, 则返回 1, 

这样, 排序算法就不用关心具体的比较过程, 而是根据比较结果直接排序。

排序函数 实现

def sort_(seq,func):
    ran=range(len(seq))
    for i in ran:
        for j in ran:
            if func(seq[i],seq[j])<0:
                seq[i],seq[j]=seq[j],seq[i]
    return seq

运行结果

x-y 升序
y-x 降序

原理就是 根据 传递的函数 去判断 x-y 小于 0 那么 我就 调换 一个 位置
否则 位置不变。
在这里插入图片描述

# sorted( )  函数的使用 
# 1.对数值进行排序
sort_list=sorted([42,422,4,2,-100,3,-10])
print('默认升序排序',sort_list)
# 逆序排序,给sorted添加reverse参数
sort_list=sorted([42,422,4,2,-100,3,-10],reverse=True)
print('逆序',sort_list)

# 对字符串ASCII  A:65   a:97
sort_list=sorted(['abc','ad','ABC','D','d','C'])
print('字符串排序',sort_list)

sort_list=sorted(['abc','ad','ABC','D','d','C'],reverse=True)
print('字符串逆序排序',sort_list)

# sorted是高阶函数,他还可以接收一个key函数来实现自定义的排序
# 对数值列表,按绝对值的大小排序
sort_list=sorted([42,422,4,2,-100,3,-10],key=abs)
print('默认升序排序',sort_list)

# 对字符串列表,忽略大小写
sort_list=sorted(['abc','ad','ABC','D','d','C'],reverse=True,key=str.lower)
print('字符串逆序排序',sort_list)


# sorted 函数  使用
# 数值进行 排序
##  默认升序

print(sorted([1, 2, 3, 4, 5, 221, 2, 3, -45]))
##  逆序排序  添加reverse 参数
print(sorted([1, 2, 3, 4, 5, 221, 2, 3, -45], reverse=True))

# 对字符串进行排序  根据 ascii 码 进行排序
print(sorted(['abc', 'DA', 'DAA', 'SDAaa', 'aasdaD', 'ab']))

# sorted 是高阶函数  还可以接受一个key函数 来实现自定义的排序

# 对数值列表进行 绝对值进行排序
print(sorted([1, 2, 3, 4, 5, 221, 2, 3, -45], reverse=True, key=abs))
# 忽略大小写 进行 逆序 也就是降序 排序
print(sorted(['abc', 'ad', 'ABC', 'D', 'd', 'C'], reverse=True, key=str.lower))

需要注意的是 sorted 生成 新的对象。

不对原来的 序列 进行操作。

在这里插入图片描述

lambda 函数

匿名函数  lambda 函数
在传入函数时, 有些时候, 不需要显式地定义函数, 直接传入匿名函数更方便。
在 Python 中, 对匿名函数提供了支持。 计算 f(x)=x2 时, 除了定义一个 f(x)的函数外,
还可以直接传入匿名函数。 使用 lambda 可以声明一个匿名函数。
lambda 表达式就是一个简单的函数。 使用 lambda 声明的函数可以返回一个值, 在调用
函数时, 直接使用 lambda 表达式的返回值。 

语法格式如下:

lambda arg1,arg2,arg3... : <表达式>

其中 arg1/arg2/arg3 为函数的参数。 <表达式>相当于函数体。 运算结果是: 表达式的运算结果


匿名函数有个限制, 就是只能有一个表达式, 不用写 return, 返回值就是该表达式的结果。
# lambda  函数使用 示例
# lambda arg1,arg2,arg3...:表达式
f=lambda a,b,c:a+b+c
print('调用:',f(3,4,5))

#匿名函数作为map高阶函数的参数  f(x)=x*x
L=map(lambda x:x*x,[1,2,3,4,5,6,7,8,9])
print(list(L))

#sorted中使用匿名函数
class Student:
    def __init__(self,name,age):
        self.name=name
        self.age=age

stu1=Student('zhangsan',21)
stu2=Student('lisi',25)
stu3=Student('wangwu',23)
# result_list=sorted([stu1,stu2,stu3],key=lambda x:x.age)
result_list=sorted([stu1,stu2,stu3],key=lambda x:x.name,reverse=True)
# for stu in result_list:
#     print('name:',stu.name,'age:',stu.age)

[print(i.name, i.age) for i in result]


也可是使用 * 进行参数 收集 。d 就是一个容器
在这里插入图片描述


闭包

根据字面意思, 可以形象地把闭包理解为一个封闭的包裹, 这个包裹就是一个函数。


然, 还有函数内部对应的逻辑, 包裹里面的东西就是自由变量, 自由变量可以随着包裹到处
游荡。

还需要有个前提, 这个包裹是创建出来的。

在 Python 语言中, 闭包意味着要有嵌套

定义

内部函数使用外部函数中定义的变量, 如果调用一个函数 A, 这个函数 A 返回一个
函数 'B', 这个'返回的函数 B '就叫作'闭包'

什么时候使用闭包?

  • 封装 - 数据隐藏 外部无法访问“嵌套函数”。
  • 贯彻 DRY(Don’t Repeat Yourself) 原则
  • 嵌套函数,可以让我们在函数内部避免重复代码。
  • 读取函数内部变量
  • 让函数常驻内存,以及函数中的变量的值始终保存在内存中
  • 在不修改源代码的情况下添加新的功能
# 闭包的概念
'''
1.什么是闭包
   闭包其实就是一个函数
2.如何创建闭包
  a.要有函数的嵌套(外部函数、内部函数)
  b.内部函数中要使用外部函数的变量
  c.外部函数必须有返回值,返回内部函数名
3.如何使用闭包
    f=funOut(100)   # 调用外部函数,用f变量指向内部函数
    print(type(f))
    result=f(200)    # 通过变量调用函数
'''

# 使用闭包,完成求两个数的和
def sum(a,b):
    return a+b

def funOut(num1):
    def funIn(num2):
        # 内部函数修改外部函数的变量
        nonlocal num1
        # 忘记了的可以看前面 我写过的。 global 和 nonlocal 
        num1+=100
        return num2+num1
    return funIn
    
# 也可以直接在后面穿参数  很方便
# f = funOut(100)(200)
# print(type(f))
# print(f)
funIn=funOut(100)
print(type(funIn)) # 运行结果 <class 'function'>
result=funIn(200)
print('两个数的和:',result) # 运行结果 两个数的和: 400
# 使用闭包求两点之间的距离
'''
   两个点  (x1,y1)  (x2,y2)
   距离: math.sqrt((x1-x2)**2+(y1-y2)**2)
'''
import math
def getDis(x1,y1,x2,y2):
    return math.sqrt((x1-x2)**2+(y1-y2)**2)
# 求点(1,1)距离原点(0,0)的距离
result=getDis(1,1,0,0)
print('点(1,1)距离原点(0,0)的距离',result)

# 求点(2,2)距离原点(0,0)的距离
result=getDis(2,2,0,0)
print('点(2,2)距离原点(0,0)的距离',result)

# 使用闭包求两点之间的距离
def getDisOut(x1,y1):
    def getDisIn(x2,y2):
        return math.sqrt((x1-x2)**2+(y1-y2)**2)
    return getDisIn

# 求点(1,1)距离原点(0,0)的距离  
# 调用外部函数
getDisIn=getDisOut(0,0)
result=getDisIn(1,1)
print('点(1,1)距离原点(0,0)的距离',result)

# 求点(2,2)距离原点(0,0)的距离
result=getDisIn(2,2)
print('点(2,2)距离原点(0,0)的距离',result)


这种写法的闭包相当于 将参数 分开 一个函数 传一部分参数进去。

不修改 原有代码的情况下 添加新功能

其实很简单 就是将原有函数 作为参数 传递 给新函数。

# 闭包的特殊用途:不修改源代码的前提下,添加新的功能
# 添加日志输出信息

import time
# 不修改 源代码的情况下 添加新的功能


def writeLog(func):
    with open('writeLog.txt', 'a', encoding='utf-8') as f:

        f.write('访问:')
        f.write(func.__name__)
        f.write('\t')
        f.write('时间:')
        f.write(time.ctime())
        f.write('\n')


def fun1():
    print('功能1')


def fun2():
    print('功能2')


def funOut(func):
    def funIn():
        writeLog(func)
        func()
        print('调用的函数:', func.__name__, '结束')

    return funIn


fun1 = funOut(fun1)
fun2 = funOut(fun2)
fun1()
fun2()

装饰器

其实装饰器就是闭包

内层函数 和 带装饰器 的函数 处理方法 是一个类型的 至少参数上是大体一致的


在 python 程序中, 装饰器就是一种闭包, 它可以是闭包的访问方式更简单。

在 Python 中使用装饰器, 需要使用一个特殊的符号“@” 来实现。 在定义装饰器函数
或类时, 使用 '@装饰器名称' 的形式将符号 "@" 放在函数或类的定义行之前。


import time


def writeLog(func):

    try:
        with open('writeLog.txt', 'a', encoding='utf-8') as f:

            f.write('访问:')
            f.write(func.__name__)
            f.write('\t')
            f.write('时间:')
            f.write(time.ctime())
            f.write('\n')
    except Exception as e:
        print(e.args)


# 使用闭包
def funOut(func):
    def funIn():
        writeLog(func)
        func()

    return funIn


@funOut  # fun1=funOut(fun1)
def fun1():
    print('功能1')

# @funOuT
# 执行过程
# fun2=funOut(fun2)  # 需要注意的是 如果 fun2=xxx 这一段,是最后执行。
# 也就是说 装饰器 在完成 最后的 return 之前  fun2 这个变量是不存在的。
# 如果有参数 顺序也是 一样的  
# 只是最后加上  a(参数) 
# 上述的过程 等于带装饰器的函数 直接  fun2() 或者 有参数的 fun2(参数)
@funOut  # 在这里加上 闭包函数的 名字就可以了
def fun2():
    print('功能2')


# 不使用装饰器 就需要这样调用 ,还是比较麻烦
# a = funOut(fun1)
# b = funOut(fun2)
# a()
# b()
# 加了装饰器 @ funOut
# 直接这样调用
fun1()
fun2()

# 多个装饰器
# 给foo函数,新增功能
# 在调用foo函数前,输出 ’I am foo‘
# 挨着功能函数最近的装饰器   依次往上 装饰
def funOut(func):
    print('装饰器1')
    def funIn():
        print('I am foo')
        func()
    return funIn

def funOut2(func):
    print('装饰器2')
    def funIn():
        print('hello')
        func()
    return funIn

@funOut2
@funOut
def foo():
    print('foo函数正在运行')

#使用闭包调用
# foo=funOut(foo)
foo()

带参数的装饰器

# 带参数的装饰器
# def fun1():
#     print('功能1')
#
# def foo():
#     print('foo函数正在运行')
# 这些装饰器 都是专用的  参数个数要一致 
# 不然 其他的 参数个数不一致的 会报错
# 或者 写多个闭包 定制
# 那么还有一个叫做通用装饰器 其实就是 可变参数  忘了的 翻前面的博客。

import time
def writeLog(func):
    print('访问了方法名:',func.__name__,'\t时间:',time.asctime())

def funOut(func):
    def funIn(x,y):
        writeLog(func)
        return func(x,y)
    return funIn

@funOut
def sum(a,b):
    return a+b

result=sum(10,20)
print('两数的和:',result)
# -------------------------------
# 功能函数三个参数
def writeLog(func):
    print('访问了方法名:',func.__name__,'\t时间:',time.asctime())
    
def funOut2(func):
    def funcIn(a,b,c):
        writeLog(func)
        return func(a,b,c)
    return funcIn
@funOut2
def add(a,b,c):
    return a+b+c

result=add(10,20,30)
print('三个数的和:',result)


通用的装饰器


# args 和 kwargs 的 详细用法
# * 需要元组  ** 需要字典
import time
def funcOut(func):
    def funcIn(*args,**kwargs):# 而作为形参的时候 这里是收集 参数
        writeLog(func)
        return func(*args,**kwargs)# 注意这里 这个 func(*args) 是展开 解包 args 元组
    return funcIn

def writeLog(func):
    print('访问方法名:',func.__name__,'\t时间:',time.asctime())

# 翻译 为  sum=funcOut(sum)
# 此函数 和  内层函数 fincIn 大体上是一类的函数(个人想法)
@funcOut  
def sum(a,b):
    return a+b

@funcOut
def add(a,b,c):
    return a+b+c

result=sum(10,20)
print('两个数的和:',result)
result=add(10,20,30)
print('三个数的和:',result)

运行 结果
在这里插入图片描述
关于 可变参数 的 * 使用 问题

(*args,**kwargs) 上面注释说的问题 就是 下面这个图 要体现的东西。

在这里插入图片描述

装饰器传递参数 @route("/index")

url_map={}

def route(option):
    def inner(func,*args,**kwargs):
        url_map[option]=func
        return func(option)
    return inner

# 过程
# @route("index")
# 假设赋值的变量为 v
# 1.  v=route("/index") 将参数"/index" 传递进route函数,并赋给 一个变量 v, 
# 2. v(index) 将index 函数作为参数传入 到 变量 v 上面 . 
# 因为  v 其实 就是 route 返回的 inner 函数 。 所以执行的是 inner(index)   
@route("/index")
def index(request):
    print(f"加载{request}页面")

url_map

整个 运行过程如下:

  1. 注册对象 url_map
  2. 注册 route 函数对象
  3. 执行@route("/index") option 形参 被 赋值 “/index”
  4. 注册嵌套函数 inner 并 return inner
  5. 将 func 指向index(request) args 指向 空元组 kwargs 指向 空字典
  6. 下面就是 执行 inner 内部的命令 将url_map 字典 填充 “/index” 作为键 指向 index(request) 函数
  7. 执行 func(option) 也就是 执行 index("/index") 这个函数 其中 request 形参 赋值为 “/index”
  8. 执行 index 函数内部的打印,因为是在 inner 内部执行的 所以 return 的为None 。因为 index 函数没有返回值
  9. 执行完毕 销毁 内存中 的 inner 函数 inner [parent=f1] 形参赋值 那一步 内存注册赋值的 空间 释放出来。

在类 class 内部使用装饰器

from operator import itemgetter
# 字典多重 排序 

class School:
    def __init__(self):
        self.db = []

    def add_student(self, name, grade):
        self.db.append({"name": name, "grade": grade})

    def sort_db(functi):
        def funcin(self, *args):
            self.db = sorted(self.db,
                             key=itemgetter("grade", "name"),
                             reverse=False)
            return functi(self, *args)

        return funcin

    @sort_db
    def roster(self):
        return [i['name'] for i in self.db]

    @sort_db
    def grade(self, grade_number):
        return [
            i['name']
            for i in filter(lambda x: x['grade'] == grade_number, self.db)
        ]


关于给类加装饰器 其实也是一样的 但是用的比较少。

这里有一个 例子。

利用装饰器 进行父类方法的重写覆盖。

继承和重写-链接

偏函数

# 偏函数 
Python 的 functools 模块提供了很多有用的功能, 其中一个就是偏函数(Partial function)。

要注意, 这里的偏函数和数学意义上的偏函数不一样


偏函数是用于对函数固定属性的函数, 作用就是把一个函数某些参数固定住(也就是设
置默认值) , 返回一个新的函数, 调用这个新的函数会更简单。


在介绍函数参数的时候, 我们讲到, 通过设定参数的默认值, 可以降低函数调用的难度。
而偏函数也可以做到这一点。 
# 偏函数 示例
print(int('12345')) #将字符串按十进制转换为整数
print('转换为八进制:',int('12345',base=8))
print('转换为十六进制:',int('12345',16))
#将'1010' 按二进制转换为整数
print(int('1010',base=2))
print(int('101010',base=2))
print(int('10101010',base=2))
#定义函数
def new_int(s):
    return int(s,base=2)
print(new_int('1010'))
print(new_int('101010'))
print(new_int('10101010'))

from functools import partial
new_int=partial(int,base=2)
print(new_int('1010'))
print(new_int('101010'))
print(new_int('10101010'))

一个例子

关于让 实例对象可迭代。
可以循环

使用 偏函数 进行默认值的设置。

from functools import partial
class Student:
    def __init__(self,name,id_):
        self.name=name
        self.id_=id_
    @property
    def description(self):
        print(f"name:{self.name}\nid:{self.id_}")
    def __iter__(self):
        travel=partial(self.travel,reverse=True)
        return travel()
    def travel(self,reverse=False):
        result=list(self.__dict__.items())
        if reverse:
            return iter(result[::-1])
        return iter(result)

一些运行效果。

在这里插入图片描述
在这里插入图片描述
我使用到偏函数的一道题。顺便复习递归。以及如何缓存递归。


高阶函数 和 递归的一些例子

# 平方
def square(x):
    return x*x


# 立方
def cube(x):
    return pow(x,3)


# 立方和
def sum_square(x,y):
    return square(x)+square(y)


# 求 a到 b 之间的和 线性迭代 计算过程
def sum_integers_iteration(a,b):
    total=0
    while a<=b:
        a,total=a+1,total+a 
    return total


# 求 a到 b 之间的和 线性递归计算过程
def sum_integers_recursion(a,b):
    if a>b:
        return 0
    else:
        return a+sum_integers_recursion(a+1,b)


# 求连续立方和 线性递归过程
def sum_cubes_recursion(a,b):
    if a>b:
        return 0
    else:
        return  pow(a,3)+sum_cubes_recursion(a+1,b)


# 求 连续序列  8/pi 最后向pi 收拢
def sum_pi_recursion(a,b):
    if a>b:
        return 0
    else:
        return 8/(a*(a+2))+sum_pi_recursion(a+4,b)



递归公共模式

# 递归公共模式
def public_recursion_summation(term,a,_next,b):
    if a>b:
        return 0
    else:
        return term(a)+ public_recursion_summation(term,_next(a),_next,b)


# 递归规则
def recursion_successor(x):
    return x+1


# 调用公共模式 实现 递归求立方和
def recursion_sum_cubes(a,b):
    return public_recursion_summation(cube,a,recursion_successor,b)

线性迭代公共模式

# 求和连续自然数
def sum_naturals(n):
    total,k=0,1
    while k<=n:
        total,k=total+k,k+1

    return total


# 求立方和
def sum_cubes(n):
    total,k=0,1
    while k<=n:
        total,k=total+pow(k,3),k+1
    return total


# pi 求和 序列
def pi_sum(n):
    total,k=0,1
    while k<=n:
        total,k=total+8/(k*(k+2)),k+4
    return total


# 公共模式  接收 上界 n  和 两个函数
def public_summation(n,term,next):
    total,k=0,1
    while k <= n:
        total,k=total+term(k),next(k)
    return total

# -------------------------------------------
# 利用公共模式  调用   写出 求连续自然数的  立方和
# 
def summation_successor(k):
    return k+1

# 公共模式立方和
def sum_cubes(n):
    return public_summation(n,cube,summation_successor)

# -----------------------

# 利用 一致函数 返回自己
def identity(k):
    return k


# 公共模式 实现 连续求和
def public_sum_naturals(n):
    return public_summation(n,identity,summation_successor)
 
# ------------------------

# 以下 是调用测试。
# sum_naturals(100)

# sum_integers_recursion(1,100)
# sum_integers_iteration(1,100)

# sum_cubes_recursion(1,3)

# 利用公共模式  调用   写出 递归求指定范围数的  立方和
recursion_sum_cubes(1,3)

# 利用公共模式  调用   写出 求连续自然数的  立方和
sum_cubes(3)

# 利用公共模式  调用   写出 求连续自然数的  和
public_sum_naturals(100)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值