zoukankan      html  css  js  c++  java
  • 名称空间与作用域、闭包函数、 装饰器

    1 名称空间与作用域

    2  闭包函数

    3  装饰器


    6.7 名称空间与作用域

    内置名称空间:

    存放的是:内置的名字与值的绑定关系
    生效:python解释器启动
    失效:Python解释器关闭

    全局名称空间:

    存放的是:文件级别定义的名字与值的绑定
    生效:执行python文件时,将该文件级别定义的名字与值的绑定关系存放起来
    失效:文件执行完毕

    局部名称空间:

    存放的是:函数内部定义的名字与值的绑定关系
    生效:调用函数时,临时生效
    失效:函数调用结束
    #python test.py
    #1、python解释器先启动,因而首先加载的是:内置名称空间
    #2、执行test.py文件,然后以文件为基础,加载全局名称空间
    #3、在执行文件的过程中如果调用函数,则临时产生局部名称空间

    加载顺序:内置---》全局----》局部名称空间

    访问名字的顺序:局部名称空间===》全局----》内置

    x=1   #全局变量
    print(x)
    print(max)  #内置变量
    
    max=2    #全局变量
    def func():
        # max=1   #局部变量
        print(max)
    func()
    
    x='gobal'  #全局变量
    def f1():
        # x=1    #局部变量
        def f2():
           # x=2   #局部变量
           def f3():
               # x=3   #局部变量
               print(x)
           f3()
        f2()
    f1()

    全局作用域(全局范围):内置名称空间与全局名称空间的名字,全局存活,全局有效,globals()

    局部作用域(局部范围):局部名称空间的名字,临时存活,局部有效,locals()

    查看作用域:globals(),locals()
    LEGB 代表名字查找顺序: locals -> enclosing function -> globals -> __builtins__
    locals 是函数内的名字空间,包括局部变量和形参
    enclosing 外部嵌套函数的名字空间(闭包中常见) #f2()上有f1(),下有f3()
    globals 全局变量,函数定义所在模块的名字空间
    builtins 内置模块的名字空间

    xxx=11111
    print(globals())  #打印全局变量和内置变量
    print(dir(globals()['__builtins__']))  #查看内置变量
    
    print(locals() is globals())  #true
    
    def func():
        yyyyyyyyyyyyyyyyyyyyyyyy=22222222
        print(globals()) #打印全局变量和内置变量
        print(locals())  #查看局部变量
    
    func()

    global关键字用来在函数或其他局部作用域中使用全局变量。但是如果不修改全局变量也可以不使用global关键字。

    x=100
    def func():
        global x   #在函数内调用全局变量
        x=1
    
    func()
    print(x)

    nonlocal关键字用来在函数或其他作用域中使用外层(非全局)变量。函 数内部一层一层往上找,没有则报错

    x='global'
    def f1():
        x=1
        def f2():
           nonlocal x  #调用外层(非全局)变量
            x=0
        f2()
        print('===f1 innter--->',x)
    
    f1()
    print(x)

    强调两点:

    1、打破函数层级限制来调用函数

    2、函数的作用域关系是在函数定义阶段就已经固定了,与调用位置无关

    x=1
    def outter():
        x=2
        def inner():
            print('inner',x)
        return inner
    
    f=outter()
    def bar():
        x=3
        f()
    bar()
    # 执行结果:inner 2

    6.8 闭包函数

    闭包函数:

    1 定义在函数内部的函数

    2 该函数的函数体代码包含对外部作用域(而不是全局作用域)名字的引用

    3 通常将闭包函数用return返回,然后可以在任意使用

    z=1
    def outer():
        x=1
        y=2
        def inner():  #闭包函数
            print(x,y)
        return inner
    
    f=outer()
    print(f.__closure__[0].cell_contents) # 1
    print(f.__closure__[1].cell_contents) # 2
    print(f.__closure__)  #(<cell at 0x00000000026D65B8: int object at 0x0000000054FBC6B0>, <cell at 0x00000000026D65E8: int object at 0x0000000054FBC6D0>)
    
    def bar():
        x=111121
        y=2222
        f()
    bar()

    应用:

    爬页面:闭包函数为我们提供了一种新的为函数传参的方式

    import requests  #pip3 install requests
    def outter(url):
        # url = 'https://www.baidu.com'
        def get():
            response=requests.get(url)
            if response.status_code == 200:
                print(len(response.text))
        return get
    
    baidu=outter('https://www.baidu.com')
    python=outter('https://www.python.org')
    baidu()
    python()
    baidu ()

    6.9 装饰器

    6.9.1 无参装饰器

    开放封闭原则:对扩展开放,对修改是封闭

    装饰器:装饰它人的,器指的是任意可调用对象,现在的场景装饰器-》函数,被装饰的对象也是-》函数

    原则:1、不修改被装饰对象的源代码

                2、不修改被装饰对象的调用方式

    装饰器的目的:在遵循1,2的前提下为被装饰对象添加上新功能

    # 错误的示范,改变了调用方式
    import time
    def index():
        time.sleep(3)
        print('welecome to index')
     
    def timmer(func):
        start=time.time()
        func()
        stop=time.time()
        print('run time is %s' %(stop-start))
     
    timmer(index)
    # 正确但不完善
    import time
    def index():
        time.sleep(3)
        print('welecome to index')
    
    def timmer(func):
        # func=index  #最原始的index
        def inner():
            start=time.time()
            func()  #最原始的index
            stop=time.time()
            print('run time is %s' %(stop-start))
        return inner
    
    index=timmer(index) #index=inner
    # print(f)
    index() #inner()

    装饰器语法:在被装饰对象正上方单独一行写上,@装饰器名

    #改进一:
    import time
    def timmer(func):
        def inner():
            start=time.time()
            res=func()
            stop=time.time()
            print('run time is %s' %(stop-start))
            return res
        return inner
    
    @timmer  #index=timmer(index)
    def index():
        time.sleep(1)
        print('welecome to index')
        return 1111
    
    res=index() #res=inner()
    print(res)
    
    #改进二:
    import time
    def timmer(func):
        def inner(*args,**kwargs):
            start=time.time()
            res=func(*args,**kwargs)
            stop=time.time()
            print('run time is %s' %(stop-start))
            return res
        return inner
    
    @timmer #index=timmer(index)
    def index(name):
        time.sleep(1)
        print('welecome %s to index' %name)
        return 1111
    res=index('egon') #res=inner('egon')
    print(res)

    6.9.2 有参装饰器

    import time
    def auth2(engine='file'):
        def auth(func): # func=index
            def inner(*args,**kwargs):
                if engine == 'file':
                    name=input('name>>: ').strip()
                    password=input('password>>: ').strip()
                    if name == 'egon' and password == '123':
                        print('login successful')
                        return func(*args,**kwargs)
                    else:
                        print('login err')
                elif engine == 'mysql':
                    print('mysql auth')
                elif engine == 'ldap':
                    print('ldap auth')
                else:
                    print('engin not exists')
            return inner
        return auth
    
    @auth2(engine='mysql') #@auth #index=auth(index) #index=inner
    def index(name):
        time.sleep(1)
        print('welecome %s to index' %name)
        return 1111
    
     res=index('egon') #res=inner('egon')
     print(res)

    6.9.3 并列多个装饰器

    import time
    def timmer(func):
        def inner(*args,**kwargs):
            start=time.time()
            res=func(*args,**kwargs)
            stop=time.time()
            print('run time is %s' %(stop-start))
            return res
        return inner
    
    def auth2(engine='file'):
        def auth(func): # func=index
            def inner(*args,**kwargs):
                if engine == 'file':
                    name=input('name>>: ').strip()
                    password=input('password>>: ').strip()
                    if name == 'egon' and password == '123':
                        print('login successful')
                        return func(*args,**kwargs)
                    else:
                        print('login err')
                elif engine == 'mysql':
                    print('mysql auth')
                elif engine == 'ldap':
                    print('ldap auth')
                else:
                    print('engin not exists')
            return inner
        return auth
    
    @auth2(engine='file')  #多个装饰器
    @timmer
    def index(name):
        time.sleep(1)
        print('welecome %s to index' %name)
        return 1111
    
    res=index('egon')
    print(res)

    6.9.4 wraps补充

    wraps: 让被装饰的函数,使用help()是看到的信息也是被装饰函数的帮助信息。

    from functools import wraps  #导入模块
    import time
    
    def timmer(func):
        @wraps(func)   #使用 wraps装饰
        def inner(*args,**kwargs):
            start=time.time()
            res=func(*args,**kwargs)
            stop=time.time()
            print('run time is %s' %(stop-start))
            return res
        # inner.__doc__=func.__doc__
        # inner.__name__=func.__name__
        return inner
    
    @timmer
    def index(name): #index=inner
        '''index 函数。。。。。'''  #index函数的帮助信息
        time.sleep(1)
        print('welecome %s to index' %name)
        return 1111
    # res=index('egon')
    # print(res)
    
    print(help(index))
  • 相关阅读:
    一步步学习微软InfoPath2010和SP2010--第六章节--发布并提交表单数据(6)--关键点
    一步步学习微软InfoPath2010和SP2010--第六章节--发布并提交表单数据(5)--管理员批准模板
    一步步学习微软InfoPath2010和SP2010--第六章节--发布并提交表单数据(4)--作为内容类型发布
    一步步学习微软InfoPath2010和SP2010--第六章节--发布并提交表单数据(3)--提交到SharePoint
    一步步学习微软InfoPath2010和SP2010--第六章节--发布并提交表单数据(2)--提升栏目
    一步步学习微软InfoPath2010和SP2010--第六章节--发布并提交表单数据(1)--发布方法
    release
    CMake 入门实战,从实例入手,讲解 CMake 的常见用法,例如aux_source_directory的用法
    为 CmakeLists.txt 添加 boost 组件
    Linux下使用CMake进行编译的时候寻找Boost库
  • 原文地址:https://www.cnblogs.com/snailgirl/p/8125021.html
Copyright © 2011-2022 走看看