• python学习笔记 day10 函数嵌套定义和闭包


    函数嵌套定义

    def func1():
        a=1
        def func2():
            print(a) #内部函数可以使用外部函数的变量
        func2()
    func1()

    外层函数func1中嵌套定义了内层函数func2,并且在外层函数中定义的变量a,在内层函数func2中也可以使用;

    外层函数中的变量a是int 类型不可变数据类型,内层函数中只可以查看不可以修改;

    如果需要修改,可以使用nonlocal声明局部变量:(类似于在函数体中使用global 声明全局变量修改)

    a=0 #全局变量
    def func1():
        a=50 #外层函数中变量a是不可变数据类型;
        def func2():
            a=2
            def func3():
                nonlocal a
                a+=100 #改变的是上一层离该函数最近的func2()中的a值
            func3()
            print("func2():a",a)  # 102
        func2()
        print("func1():a",a)  # 50
    func1()
    print("全局:a",a)  # 0

    运行结果:

    nonlocal 只作用于局部变量;只修改上一层中离该内层函数最近的函数中的变量,;

    如果在所有的上层函数中都找不到要修改的该局部变量,则报错(因为nonlocal只作用于局部变量,global声明的才是全局变量)

    函数名其实就是内存地址,函数名可以赋值:

    def func1():
        print("hello world")
    func1()
    func2=func1  #函数名可以相当于变量进行赋值操作;这样func2和func1这两个函数名都可以指向同一个内存地址
    func2()

    函数名可以作为容器类型的参数:

    def func1():
        print("hello world")
    # func1()
    func2=func1  #函数名可以相当于变量进行赋值操作;这样func2和func1这两个函数名都可以指向同一个内存地址
    # func2()
    
    L=[func1,func2]
    for func in L:
        func() #func1() func2()

    函数名可以作为另一个函数的参数:

    def func1():
        print("hello world!")
    
    def func2(f):  #参数是一个函数名,而不是普通的变量~
        f()
        print("hello world~")
    
    func2(func1)

    函数名可以作为另一个函数的返回值:

    def func1():
        def func2():
            print("hello world!")
        return func2  #将内部定义的函数func2函数名返回
    f=func1()  #因为func1()函数返回的就是一个函数 f=func2
    f() #func2()

     闭包:---嵌套函数;内部函数必须要调用外部函数中的变量

    def func1():
        a=1 #外部函数中定义的变量
        def func2():  
            print(a)
        return func2  #把一个函数名作为返回值
    f=func1()  #f=func2
    f()

    如果内层函数不调用外部函数中的变量,或者调用的是全局变量都不能称之为闭包函数(闭包指的是内层函数):

    a=1
    def func1():
        # a=1 #外部函数中定义的变量
        def func2(): #使用的是全局变量a,不是闭包函数
            print(a)
        return func2  #把一个函数名作为返回值
    f=func1()  #f=func2
    f()

    一般写其实可以保护外部函数中被内层函数使用的变量,延长存在周期:

    def func1():
        a=1
        print(a)
    func1()  #会创建一个局部变量a,随着函数func1()执行完会被释放;
    func1()  #又会创建一个局部变量a,,,,随着函数func1的调用会被重复创建;

     推荐做法(使用闭包):

    def func1():
        a=1
        def func2():
            print(a)
        return func2  #外部函数返回的其实是一个函数名;
    f=fun1() #f是一个全局变量,它指向一个内部函数,随时可以进行调用f() 所以外部函数的a并不会随着函数的结束而被释放,而是会留在内部命名空间中,等待f()时被调用
    f()

    这样a变量不会随着f()的调用重复创建,随着func1()函数执行完毕被释放掉,而是由于f全局变量(其实是一个函数名=func2)可能被调用会留在内部命名空间中;

     比如其实再写爬虫,爬取一些网站时我们也可以使用闭包:在多次调用函数时不用重复创建url变量:

    不建议:

    from urllib.request import urlopen
    def get_url():  #未使用闭包,这样每次调用get_url()时就会重复创建url变量
        url='http://www.xiaohua100.cn/index.html'
        res=urlopen(url).read()
        print(res)    
    get_url()

    推荐使用闭包:

    from urllib.request import urlopen
    def get_url():  #使用闭包,这样每次调用get_url()时就不会重复创建url变量
        url='http://www.xiaohua100.cn/index.html'
        def inner():   #闭包函数
            res=urlopen(url).read()
            print(res)
        return inner
    inn=get_url()  #全局变量inn指向内层函数,由于inn()随时可能被调用,随意外层函数的url会保留在局部命名空间中;
    inn()
    inn()
    talk is cheap,show me the code
  • 相关阅读:
    Tensorflowlite移植ARM平台iMX6
    人生信条集
    浅谈聚类
    常用距离度量方法大全
    sklearn学习小结
    SpringBoot 2.x版本+MultipartFile设置指定文件上传大小
    SpringBoot无法访问webapp目录下的文件
    idea搜索不到任何插件
    Caused by: org.springframework.data.mapping.PropertyReferenceException: No property id found for type Users!
    Annotation-specified bean name 'userDaoImpl' for bean class [***] conflicts with existing, non-compatible bean definition of same name and class [***]
  • 原文地址:https://www.cnblogs.com/xuanxuanlove/p/9560367.html
Copyright © 2020-2023  润新知