zoukankan      html  css  js  c++  java
  • Python基础-----函数式编程含义及特点(及尾递归)

    一、定义
    函数式就是用编程语言去实现数学函数。这种函数内对象是永恒不变的,要么参数是函数,要么返回值是函数,没for和while循环
    所有的循环都由递归去实现,无变量的赋值(即不用变量去保存状态),无赋值即不可改变。
    二、特点
    1、不可变数据
    不可变:不用变量保存状态,不修改变量
    a. 非函数式
    a = 1
    def test():
    global a
    a += 1
    return a
    test()
    print(a)
    >>> 2
    b. 函数式
    n = 1
    def test1(n):
    return n+1
    print(test1(2))
    print(n)
    >> 3
    1
    2、第一类对象
    第一类对象:函数即变量
    a.函数名可以作为参数传递
    def a(n):
    print(n)
    def b(name):
    print('My name is %s'%name)
    a(b)
    >>> 上述调用为:b不带括号则表示b函数的内存地址,将内存地址作为实参传递给a函数,则a函数打印的为b函数的内存地址
    a(b('Liming'))
    >>> 'My name is Liming'
    None
    上述调用为:首先会执行函数b,则先打印出‘My name is Liming’,但是b函数没有定义返回值,则默认为None
    则将None作为实参传递给a函数,则a函数打印出None
    b.返回值可以是函数名
    def a():
    print('from a')
    def b():
    print('from b')
    return a
    n = b()
    n()
    >>> 'from a'
    'from b'
    3、尾调用优化(尾递归)
    尾调用:在函数的最后一步调用另外一个函数(最后一行不一定是函数的最后一步)
    尾调用优化:尾调用的关键就是在于函数的最后一步调用别的函数,这样的好处是:根据函数即‘变量’的定义,
    定义a函数,a内调用b函数,b内调用c函数,在内存中会形成一个调用记录,又称调用帧,用于保存调用位置和内部变
    量等信息,即a->b->c直到c返回结果给b,c的调用记录才会消失,b返回给a,b的调用记录消失,a返回结果,a的调用
    记录消失,所有的调用记录都是先进后出,形成了一个调用栈。尾调用由于是函数的最后一步操作,所以不需要保留外
    层函数的调用记录,因为调用位置、内部变量等信息都不会用到了,只要直接用内层函数的调用记录,取代外层函数的
    调用记录就可以了。
    def bar(n)
    return n
    def foo(x):
    return bar(x)
    print(foo(3))
    >>> 3
    上述foo(3)就等于bar(3),也就是说foo在最后一步调用了bar,然后foo的调用记录就清楚了,剩下的就是bar
    自己的事情了。所以内存里永远只保留一个调用记录。

    尾递归:函数调用自身成为递归,如果尾调用自身,就成为尾递归。
    尾递归特点:重复相同的事情,每次重复会使问题规模减少。
    尾递归举例:
    问题:师傅,北京怎么去啊?
    解决方法:a去问b,b不知道,b去问c,c去问d,最有由d得出结果,此过程可以发现,问题最有只需要d去
    结局即可,a b c都无需保存任何记录,不干事,因为他们啥都不知道。
    尾递归优点:递归通常非常耗费内存,因为需要同时保存成千上百个调用记录,很容易发生‘栈溢出’错误。
    但对于尾递归来说,由于只存在一个调用记录,所以不会发生‘栈溢出’错误。
    def cal(l):
    print(l)
    if len(l) == 1:
    return l[0]
    first,second,*args = l
    l[0] = first + second
    l.pop(1)
    return cal(l)
    x = cal([i for i in range(10)])
    print(x)
    >>> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    [1, 2, 3, 4, 5, 6, 7, 8, 9]
    [3, 3, 4, 5, 6, 7, 8, 9]
    [6, 4, 5, 6, 7, 8, 9]
    [10, 5, 6, 7, 8, 9]
    [15, 6, 7, 8, 9]
    [21, 7, 8, 9]
    [28, 8, 9]
    [36, 9]
    [45]
    45
    上例就是用到尾递归,最终求得1~9的和
  • 相关阅读:
    'index.js' does not match the corresponding name on disk: '. ode_modules
    onload()方法只能在body标签中调用吗?怎么调用多个多个方法?
    HTML5新属性在Google浏览器中不能显示的问题
    HTML引入JS、CSS的各种方法
    框架、架构、设计模式的区别
    npm 命令 --save 和 --save-dev 的区别
    软件开发的权限控制和权限验证
    报错:Something is already running on port 8000.
    $stateProvider resovle 无法找到的原因
    git 统计代码量 shell脚本
  • 原文地址:https://www.cnblogs.com/Meanwey/p/9741228.html
Copyright © 2011-2022 走看看