• python基础—函数嵌套与闭包


    python基础—函数嵌套与闭包

     

    1、名称空间与作用域

     

     1 名称空间分为:

     

       1 内置名称空间   内置在解释器中的名称

     

       2 全局名称空间   顶头写的名称

     

       3 局部名称空间

     

    2 找一个名称的查找顺序:先在局部名称空间找,再到全局名称空间找,再到内置名称空间

     

    3 Globals()  查看全局名称空间的内容

     

      Locals()   查看局部名称空间的内容

     

    4 全局作用域包含内置名称空间和全局名称空间

     

       局部作用域包含局部名称空间

     

     

    1 查看内建名称空间的内容:

     

     

    2 作用域

    x=1
    def foo():
        x=100
        print(x)
    foo()
    print(x)
    

    输出结果:

    100
    1
    

    3 一定要注意函数要先定义,后使用

    def foo():
        print("from foo")
        bar()
    def bar():
        print("from bar")
    foo()
    

    输出结果:

    from foo
    from bar
    

     

    def foo():
        print("from foo")
        bar()
    foo()
    def bar():
    print("from bar")
    

    输出结果:

    NameError: name 'bar' is not defined  #报错
    

    4 Globals()  查看全局名称空间的内容

      Locals()   查看局部名称空间的内容

    x=1
    def func():
        print("from func")
        x=2
        print(globals())
        print(locals())
    func()
    print(globals())
    print(locals())
    

    输出结果:

    from func
    {'x': 1, '__cached__': None...
    {'x': 2}
    {'x': 1, '__cached__': None...
    {'x': 1, '__cached__': None...
    

    2、函数嵌套与静态嵌套域

    嵌套调用

    嵌套调用作用:将一个大的功能细化成各种小的函数功能并调用

    def my_max(x,y):
        res=x if x >y else y
        return res
    print(my_max(10,100))
    def my_max4(a,b,c,d):
        res1=my_max(a,b)
        res2=my_max(res1,c)
        res3=my_max(res2,d)
        return res3
    print(my_max4(1,20,3,4))
    

    输出结果:

    100
    20
    

    在函数内定义的函数 在外面不能用到

    def f1():
        def f2():
            def f3():
                pass
        print("---->f1")
        f2()
    f2()
    

    输出结果:

    NameError: name 'f2' is not defined  #报错
    

    #嵌套定义   

    x找值的过程:先在局部名称空间找,再到上一级的局部名称空间找,再到全局名称空间找,再到内置名称空间

    x=0
    def f1():
        #x=1
        print("---f1---",x)
        def f2():
            #x=2
            print("---f2---",x)
            def f3():
                #x=3
                print("---f3---",x)
            f3()
        f2()
    f1()
    

    输出结果:

    ---f1--- 0
    ---f2--- 0
    ---f3--- 0
    

    3、函数对象

    函数被称为第一类对象,函数可以被当做数据传递

    (1)函数可以被赋值

    直接输出函数名的值: 就是函数在内存中的地址

    def foo():
        print("foo")
    print(foo)
    

    输出结果: 

    <function foo at 0x000000DD32CAAD90>
    

    函数可以被赋值:将函数名代码的值赋给变量  

    def foo():
        print("foo")
    f=foo
    print(f)
    f()
    

    输出结果:

    <function foo at 0x0000003AEBEBAD90>
    foo
    

    (2)函数可以作为参数传递

    函数可以作为参数传递

    def foo():
        print("foo")
    def bar(func):
        print(func)
        func()
    print(bar(foo))
    

    输出结果:

    <function foo at 0x000000A351B4AD90>
    foo
    None
    

     

    (3)函数可以作为返回值

    函数可以作为函数的返回值

    def foo():
        print("foo")
    def bar(func):
        print(func)
        func()
        return func
    f=bar(foo)
    print(f)
    f()
    

    输出结果:

    <function foo at 0x000000BFD82CAD90>
    foo
    <function foo at 0x000000BFD82CAD90>
    foo
    

    (4)函数可以作为容器类型的元素

    函数作为字典的键的值:

    def add():
        print("=======>function add")
    def search():
        print("=======>function search")
    def delete():
        print("=======>function delete")
    def change():
        print("=======>function change")
    def tell_msg():
        msg='''
        search:查询
        add:添加
        delete:删除
        change:修改
        create:新建
        '''
        print(msg)
    def create():
        print('=======>function create')
    
    cmd_dic={
        'search':search,
        'add':add,
        'delete':delete,
        'change':change,
        'create':create
    }
    while True:
        tell_msg()
        choice=input("please input your choice:")
        cmd_dic[choice]()
    

    4、函数闭包

    (1)函数闭定义

    闭包:首先必须是内部定义的函数,该函数包含对外部作用域而不是全局作用域名字的引用

    定义:内部函数的代码包含对外部函数的代码的引用,但一定不是对全局作用域的引用

    闭包的基本形式是:

      在函数F1中,定义F2,F2只能引用F1定义的变量,之后F1函数返回F2的函数名字

      这样就保证了可以将F1的执行结果赋予给一个变量,该变量可以在之后的任何时刻随时可以运行 

    使用闭包的好处:自带状态即变量,可以不用传参就用,方便。

    闭包(closure)是函数式编程的重要的语法结构。不同的语言实现闭包的方式不同。Python以函数对象为基础,为闭包这一语法结构提供支持的 (我们在特殊方法与多范式中,已经多次看到Python使用对象来实现一些特殊的语法)。Python一切皆对象,函数这一语法结构也是一个对象。在函数对象中,我们像使用一个普通对象一样使用函数对象,比如更改函数对象的名字,或者将函数对象作为参数进行传递。

     

      

     (2)简单闭包举例

    x=1000
    def f1():
        x=1
        def f2():
            print(x)
        return f2
    f=f1()
    print(f)
    x=123
    f()
    

    输出结果:

    <function f1.<locals>.f2 at 0x000000C02BD1AF28>
    1
    

    (3)闭包的__closure__变量

    闭包都有__closure__属性

    __closure__对象会返回闭包应用外围作用域的变量信息。f.__closure__保存外围作用域的变量内存地址,f.__closure__[0].cell_contents存放的是外围作用域的变量的值。

    对于那些不是闭包的函数对象来说,__closure__ 属性值为 None。

    x=1
    def f1():
        x=1000
        y=2
        def f2():
            y
            print(x)
        return f2
    f=f1()  #f ---> 内部的函数f2
    f()
    print(f.__closure__)
    print(f.__closure__[0])
    print(f.__closure__[0].cell_contents)
    print(f.__closure__[1])
    print(f.__closure__[1].cell_contents)
    

    输出结果:

    1000
    (<cell at 0x000000429E165D68: int object at 0x000000429E0A9EB0>, <cell at 0x000000429E165D98: int object at 0x0000000059C0EF50>)
    <cell at 0x000000429E165D68: int object at 0x000000429E0A9EB0>
    1000
    <cell at 0x000000429E165D98: int object at 0x0000000059C0EF50>
    2
    

    举例:__closure__ 属性值为 None

    x=1
    def f1():
        def f2():
            print(x)
        return f2
    f=f1()  #f ---> 内部的函数f2
    f()
    print(f.__closure__)
    

     输出结果为:

    1
    None
    

    (4)闭包应用

    Windows中cmd中执行pip install requests 安装requests库件

    爬baidu网站的程序

    from  urllib.request import urlopen
    def get(url):
        return urlopen(url).read()
    print(get('http://www.baidu.com'))
    print(get('http://www/python.org'))
    

    将上面”爬百度”的程序修改成闭包模式:

    from  urllib.request import urlopen
    def f1(url):
        def f2():
            print(urlopen(url).read())
        return f2
    baidu=f1('http://www.baidu.com')
    python=f1('http://www.python.org')
    baidu()
    python()
    
  • 相关阅读:
    python_day10 线程
    python_day9 回调函数
    python_day9 进程池
    python_day9 共享数据
    python-day9 队列
    python_day9 其他方法和属性
    python_day9 多进程socket
    原生js实现ajax 发送post请求/原生JS封装Ajax插件(同域、jsonp跨域)
    css设置时父元素随子元素margin值移动
    zepto默认的webkit和zepto不兼容
  • 原文地址:https://www.cnblogs.com/niejinmei/p/6757653.html
Copyright © 2020-2023  润新知