python函数式编程基础(二)

本文在上一篇文章:python函数式编程基础(一)的基础上继续介绍函数的闭包概念,递归以及高阶函数

python函数式编程基础(一):https://blog.csdn.net/Geroge_lmx/article/details/80740484

回顾:闭包是一个内嵌函数引用了外部嵌套函数的变量,并且外部嵌套函数返回的是内嵌函数

准备知识:局部变量,全局变量以及作用域

一.变量及作用域

局部变量:
    1.定义在函数内部的变量,函数的形参也属于局部变量
    2.只能在函数内部使用
    3.在函数调用时被创建,调用结束后自动销毁

全局变量:

    1.定义在函数外部,模块内部的变量
    2.所有的函数都可以直接“访问”全局变量
    3.对于不可变数据类型,函数内部不能直接通过赋值语句来改变全局变量
    4.对于可变数据类型,函数内部可以直接通过赋值语句来改变全局变量

python的作用域:LEGB

    做用域也叫命名空间,是访问变量时查找变量名的范围空间
    L(local):局部作用域(函数内)
    E(Enclosing):外部嵌套函数作用域
    G(Globals):全局作用域(模块内)
    B(Builtin):python内置模块的作用域

变量名查找顺序:

    查找顺序:L --> E --> G --> B

global 语句:

    作用:
        全局声明,将函数内部赋值的变量映射到全局作用域
    语法:
        global 变量1, 变量2, ...
    说明:
        1.在函数内部修改绑定不可变数据类型的全局变量时,必须用global声明,否则将被视为局部变量
        2.全局变量在函数内部可以不经过声明直接访问
        3.禁止先创建局部变量,再用global声明为全局变量

nonlocal语句:

    作用:nonlocal声明,变量不是局部变量,而是外部嵌套函数内的变量
    语法:
        nonlocal 变量1,变量2
    说明:
        1.nonlocal语句只能在内嵌函数内使用
        2.访问nonlocal变量将对外部嵌套函数作用域内的变量产生影响
        3.当有2层或2层以上的函数嵌套时,访问nonlocal变量只对最近一层的变量进行操作

二.闭包

闭包的三个条件:

    1.必须有内嵌函数
    2.内嵌函数必须引用外部函数中的变量
    3.外部函数返回值必须是“内嵌函数”
    通常情况下,在函数调用结束后,函数内部变量会自动被释放掉。但闭包不同,如果外部嵌套函数在调用结束后,发现自己的变量在内嵌函数中有使用,则外部函数在调用结束后,在返回内嵌函数的同时,也会将这些变量传递给内嵌函数,一起绑定起来。这样,外部函数调用结束后,内嵌函数被调用时仍可以访问外部嵌套函数作用域内的变量。如下:
def outer(start):
    step1 = 1
    step2 = [1]
    def iner():
        #修改enclosing变量必须进行声明,告诉解析器step不是局部变量,而是enclosing变量
        nonlocal step1
        sum_num1 = start + step1 #仅访问start的值,而不做修改,故start无需声明
        sum_num2 = start + step2[0] #对于可变数据类型,无需声明
        print('start + step1 = %d' % sum_num1)
        print('start + step2[0] = %d' % sum_num2)
        step1 += 1
        step2[0] += 2
    return iner

a1 = outer(10)
a1()
print('-------------------')
a1()
print('-------------------')
a1()

运行结果:
start + step1 = 11
start + step2[0] = 11
-------------------
start + step1 = 12
start + step2[0] = 13
-------------------
start + step1 = 13
start + step2[0] = 15

三.递归函数 Recursion

    1.函数直接或间接地调用自身,如:

def func():
            '''直接调用自己,进入递归'''
            func()
        func()

        def func1():
            '''函数间接调用自身'''
            func2()

        def func2():
            func1()

        func1()
        print("递归完成")
     2.备注:
        1.递归一定要控制递归的层数,当符合一定条件时,要终止递归调用;
        2.几乎所有的递归,都能用while循环来代替
        3.每次调用函数时,都会开辟一块独立的空间
      3.优点:
        简化问题,思路清晰,代码简洁(在适合使用递归地问题上,使用递归)
     4.缺点:
        递归因系统环境影响大,当递归深度太大时,可能会得到不可预知的结果
        备注:
            1.递归深度默认为1000    
            2.sys.getrecursionlimit()--->可以查看递归深度
            3.sys.setrecursionlimit(n)--->可以修改递归深度
     5.递归的两个阶段:
        递推阶段:
            由问题出发,从未知到已知,按递归公式递推,直到满足终止条件。
        回归阶段:
            由递归终止条件得到的结果出发,逆向逐步代入递归公式,回归问题。
     6.递归的实现方法:
        先假设函数已经实现

     7.实例:

     ①计算等差数列1,2,3...n的和

def mysum(n):
    if n == 1:
        return 1
    return n + mysum(n-1)

print(mysum(100))

运行结果:
5050

     ②写一个函数求n的阶乘

def myfac(n):
    '''函数递归调用'''
    if n==1:
        return 1
    return n * myfac(n-1)

print('5的阶乘是:', myfac(5))

运行结果:
5的阶乘是: 120

     ③L = [[3, 5, 8], 10, [[13, 14], 15, 18], 20]
         1) 递归打印列表内的所有元素
         2) 计算列表中所有元素的和

def print_list(L):
    for item in L:
        if type(item) is not list:
            print(item,end=' ')
        else:
            print_list(item) #递归的思想

def sum_list(L):
    sum_number = 0
    for item in L:
        if type(item) is not list:
            sum_number += item
        else:
            sum_number += sum_list(item)
    return sum_number

L = [[3, 5, 8], 10, [[13, 14], 15, 18], 20]
print_list(L)
print()
print("返回这个列表中所有元素的和:", sum_list(L))

猜你喜欢

转载自blog.csdn.net/Geroge_lmx/article/details/80791803
今日推荐