函数的作用域和匿名函数、闭包、回调

一、匿名函数:

1、filter函数,可以过滤出列表中大于3的数据,但是使用都需要提前定义一个函数,有没有更加简便的方式呢?

def f(o):   # 过滤器
    if o>3:
        print(o)

list(filter(f,[3,1,5,9,7,10]))

运行截图:

 2、匿名函数(lambda后面是空格)

 

# lambda   参数 : 表达式
print(list(filter(lambda o:o>3,[3,1,5,9,7,10])))  # 不需要使用函数就能够完成

运行截图:  

二、函数作用域 

思考:

在函数里面也有可以定义变量,那函数里面的变量名如果和函数外面的变量名重名,会相互影响吗?

1、 函数里面可以访问外面的变量,但不可以修改

a=1 # 先声明变量 a  # 把外面的当做爸爸
def f():          # 儿子
    print(a)

f() 

运行截图:

 2、外部不能访问函数内部变量,函数里面和函数外部变量名可以相同,互相不影响

a=1  # 爸爸
def f():
    a=123
    print(a)

f()  # 123  # 函数里面有的这个变量就自己,外面的不可以访问函数里面的变量
print(a)  # 打印的是函数外面的a===函数里面和外面的相互不受影响

运行截图:

 3、函数里面不能修改函数外部变量

a = 1  # 爸爸
def f():  # 儿子
    a = a + 1  # 不可以改变爸爸的变量
    print(a)


f()  # 3  函数里面只可以访问不可以修改

运行截图:

 4. global(全局变量) 和 nonlocal(局部变量) 

a = 1  # 爸爸    ===称为全局变量
def f():  # 儿子  ===局部变量
    global a # 声明外面变量===外面的变量就发生了变化
    a = a + 1  # global 声明后可以改变爸爸的变量
    print(a)
    print(id(a))

f() 
print(a)
print(id(a))     # global声明后里外输出的值均为2,id也是一样的

运行截图:

 如果不声明全局变量,那么函数里面不能修改函数外部变量

 以上总结:局部的可以拿全局变量,全局不可以拿局部的。

5、 函数在什么时候执行?  

a=1
def f():
    a=2
    # 函数里面可以放任何东西
    def f2():
        a=3
        print(123)
#
f()  # 所以这样写f2函数不会执行
print(a)

运行截图:

调用f2() 才可以执行对应代码块 ==  (函数名+括号) 

a=1
def f():
    a=2
    # 函数里面可以放任何东西
    def f2():
        a=3
        print(123)
    f2()

f()  # 函数在什么时候执行?
# f2() 不可以这样写
print(a)

运行截图:

如果注释这里的变量值a就向上一级要值,儿子向=====》》》爸爸要值
a=1
def f():
a=2
print(a) # 2
# 函数里面可以放任何东西
def f2():
# a=3 # 如果注释这里的变量值a就向上一级要值 儿子=====》》》爸爸
print(a)
print(123)
f2()

f() # 函数在什么时候执行?(函数名+括号)
print(a)

运行截图:

 如果爸爸没有就向爷爷咨询要值 

a=1
def f():
    # a=2
    # print(a)  # 2  # 如果爸爸没有就向爷爷咨询要值 一层一层的取值
    # 函数里面可以放任何东西
    def f2():
        # a=3  # 如果注释这里的变量值a就向上一级要值 儿子==》》爸爸 如果爸爸没有就向爷爷咨询要值
        print(a)
        print(123)
    f2()

f()  # 函数在什么时候执行?(函数名+括号)  所以这样写f2函数不会执行
print(a)

运行截图:

 global a 全局变量的作用,改变外部函数参数值大小

a=1
def f():
    global a
    a=a+5
    print(a)  # 6
    # 函数里面可以放任何东西
    def f2():
        # a=3  #
        print(a) # 6
        print(123)
    f2()

f()  # 函数在什么时候执行?(函数名+括号)  
print(a)  # 6

运行截图:

 # 注释global a后:  

a=1
def f():
    # global a
    a=2
    print(a)  
    # 函数里面可以放任何东西
    def f2():
        # a=3  
        print(a) 
        print(123)
    f2()

f()  # 函数在什么时候执行?(函数名+括号)
print(a)

运行截图:

 nonlocal: 在函数嵌套函数的情况下,同样也有函数作用域的问题,但是python3中提供了方便,只需要使用nonlocal就可以在里层函数内部修改外部函数变量

a=1
def f():
    # global a
    a=2
    print(a)  
    # 函数里面可以放任何东西
    def f2():
        nonlocal a  # 声明局部(改变的是上级局部变量)
        # a=3  
        a=a+5
        # print(a)
        print(123)
    f2()
    print(a)
f()  # 函数在什么时候执行?  
print(a)

运行截图:

 global a # 声明全局变量 

a=1
def f():
    # global a
    a=2
    print(a)
    # 函数里面可以放任何东西
    def f2():
      
        global a  # 声明全局变量 
        # a=3  
        a=a+5
        print(a)
        print(123)
    f2()

f()  # 函数在什么时候执行?(函数名+括号)  所以这样写f2函数不会执行
print(a)

运行截图:

总结:

 

三、闭包

思考:函数里面可以再定义函数,那函数里面定义的函数可以在外面调用吗?如果可以的话,要怎么做呢?

'''
闭包是函数里面嵌套函数,外层函数返回里层函数,这种情况称之为闭包
闭包是概念,不是某种函数类型,和递归的概念类似,就是种特殊的函数调用
闭包可以得到外层函数的局部变量,是函数内部和函数外部沟通的桥梁

'''
例1:
def f():
    print('这里是f函数')
    def f2():

        print('这里是f2函数')
    return f2  # 返回的是f2 函数
    # return 123  # 返回的是123

a=f()   # a====f2函数  (函数名+括号) 代表调用
a() # 调用f2  闭包:外层函数返回内层函数
print(a) # 返回的是123
# print(f)

运行截图:

例2:

def f():
    print('这里是f函数')
    def f2():

        print('这里是f2函数')
    # return f2  # 返回的是f2 函数
    return 123  # 返回的是123

a=f()   # a====f2函数  (函数名+括号) 代表调用
# a() # 调用f2  闭包:外层函数返回内层函数
print(a) # 返回的是123

运行截图:

 例3:

def f():
    print('这里是f函数')
    def f2():

        b=1
        print('这里是f2函数')
        return b+2

    return f2  # 对于f2函数来说哪里调用的就返回哪里

a=f()   # a====f2函数  (函数名+括号) 代表调用 并传给a,由a接受
l=a()   # 代表调用f2  闭包:外层函数返回内层函数
print(l)

运行截图: 

 例4:

def fun(a):
    print(a)

    def fun1():
        print(a,11)

    return fun1  # 调用不行执

a = fun(3)
a()  #  相当于 fun(3)() 调用fun1

运行截图:

 

四、递归和回调函数

思考:

1、函数里面可以自身调用自身吗?

递归中可以函数自身调用自身,但是使用时类似于条件循环一样,要有递归的终止条件

递归应用:

使用递归时,常常可以让代码更加简洁 递归会占用比较多的内存,当递归次数比较多时,性能就会降低, 因此不建议多使用递归

例1:

递归:自己调用自己称为递归

def f(n):
    if n==1:
        return 1
    return f(n-1)*n
# 5*f(4)  5*4*f(3) 5*4*3*f(2) 5*4*3*2*f(1)
a=f(5)
print(a)

运行截图:

2、 回调函数:一个函数当做是一个参数传给另一个函数--- 称为回调

自身是一个函数,只是被传入到另一个函数当中,供其调用 回调函数不一定会被调用,是否调用由被传入函数的内部逻辑决定

例1:

def f():
    print('这里是f函数')   # f 为回调函数
def f2(o):
    print('这里是f2函数')
    # o为参数
    o()  # ====说明在调用f函数

f2(f)

运行截图:

 例2:

def f(a):
#     print(a)
#
# def f2(o):
#     print('这里是f2函数')
#     # o为参数
#     o(15)  # ====说明在调用f函数,哪里调用就在哪里传参!
#
# f2(f)

运行截图:

 

posted @ 2023-08-23 00:45  人生努力努力努力就好  阅读(41)  评论(0)    收藏  举报