名称空间与作用域、闭包函数、 装饰器

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))

 

posted on 2017-12-27 12:59  蜗牛也是妞  阅读(242)  评论(0编辑  收藏  举报