Python-函数进阶

一、名称空间:存放变量名与对应值绑定关系的地方。

分为三种:locals(),是函数内的名称空间,包含局部变量与形参;globals():全局变量,函数定义所在模块的名字空间;builtins():内置模块的名字空间。

level = 'l0'
n = 22
def func():
    level = 'l1'
    n = 33
    print(locals())

    def outer():
        n = 44
        level = 'l2'
        print(locals(),n)

        def inner():
            level = 'l3'
            print(locals(),n)
        inner()
    outer()
func()

#打印 func()/outer()/inner()

{'level': 'l1', 'n': 33}
{'level': 'l2', 'n': 44} 44
{'level': 'l3', 'n': 44} 44

#名称空间查找顺序:局部名称空间--->全局名称空间--->内置名称空间

不同变量的作用域不同是由这个变量所在的命名空间决定的。

作用域即范围:全局范围:全局存活,全局有效;局部范围:临时存活,局部有效。

#1、作用域即范围
        - 全局范围(内置名称空间与全局名称空间属于该范围):全局存活,全局有效
      - 局部范围(局部名称空间属于该范围):临时存活,局部有效
#2、作用域关系是在函数定义阶段就已经固定的,与函数的调用位置无关,如下
x=1
def f1():
    def f2():
        print(x)
    return f2
x=100
def f3(func):
    x=2
    func()
x=10000
f3(f1())

#3、查看作用域:globals(),locals()


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

二、闭包

定义:内部函数包含对外部作用域,而非全局作用域的引用。之前我们都是通过参数将值传给函数,闭包给我们提供了一种新的方式。

 outer():
    name='alex'

    def inner():
        print("在inner里面打印外层函数的变量", name)
    return inner

f = outer()
f()

 闭包的意义:

返回的函数对象,不仅仅是一个函数对象,在该函数外层还包裹着一层作用域,这使得函数无论在何处调用,都优先使用自己外层包裹的作用域。应用:延迟计算。

def counter():
    n = 0

    def incr():
        nonlocal n
        x = n
        n += 1
        return x

    return incr


c = counter()
print(c())
print(c())
print(c())
print(c.__closure__[0].cell_contents)  # 查看闭包的元

 三、装饰器

定义:装饰器他人的器具,本身可以是任意可调用对象,被装饰者也可以是任意可调用对象。

强调装饰器的原则:1 不修改被装饰对象的源代码 2 不修改被装饰对象的调用方法。

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

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

装饰器就是闭包的一种应用场景

装饰器的使用:

1、无参数的使用

import time
def timmer(func):
    def wrapper(*args,**kwargs):
        start_time=time.time()
        res=func(*args,**kwargs)
        stop_time=time.time()
        print('run time is %s' %(stop_time-start_time))
        return res
    return wrapper

@timmer
def foo():
    time.sleep(3)
    print('from foo')
foo()

2、有参数的使用

def auth(driver='file'):
    def auth2(func):
        def wrapper(*args,**kwargs):
            name=input("user: ")
            pwd=input("pwd: ")

            if driver == 'file':
                if name == 'egon' and pwd == '123':
                    print('login successful')
                    res=func(*args,**kwargs)
                    return res
            elif driver == 'ldap':
                print('ldap')
        return wrapper
    return auth2

@auth(driver='file')
def foo(name):
    print(name)

foo('egon')
原文地址:https://www.cnblogs.com/hexiaorui123/p/9995475.html