python闭包,装饰器&语法糖

所谓闭包,就是将组成函数的语句和这些语句的执行环境打包在一起时,得到的对象:

听上去的确有些复杂,还是用一个栗子来帮助理解一下。假设我们在foo.py模块中做了如下定义:
#foo.py
filename = "foo.py"
def call_func(f):
    return f()    #如前面介绍的,f引用一个函数对象,然后调用它


在另一个func.py模块中,写下了这样的代码:
#func.py
import foo      #导入foo.py
filename = "func.py"
def show_filename():
    return "filename: %s" % filename
if __name__ == "__main__":
    print foo.call_func(show_filename)   #注意:实际发生调用的位置,是在foo.call_func函数中


当我们用python func.py命令执行func.py时输出结果为:
chiyu@chiyu-PC:~$ python func.py 
filename:func.py


很显然show_filename()函数使用的filename变量的值,是在与它相同环境(func.py模块)中定义的那个。尽管foo.py模块中也定义了同名的filename变量,而且实际调用show_filename的位置也是在foo.py的call_func内部。


而对于嵌套函数,这一机制则会表现的更加明显:闭包将会捕捉内层函数执行所需的整个环境:
#enclosed.py
import foo
def wrapper():
    filename = "enclosed.py"
def show_filename():
        return "filename: %s" % filename
    print foo.call_func(show_filename)    #输出:filename: enclosed.py


实际上,每一个函数对象,都有一个指向了该函数定义时所在全局名称空间的__globals__属性:
#show_filename inside wrapper#show_filename.__globals__

{'__builtins__': <module '__builtin__' (built-in)>,        #内建作用域环境'__file__': 'enclosed.py',         'wrapper': <function wrapper at 0x7f84768b6578>,      #直接外围环境'__package__': None,            '__name__': '__main__',        'foo': <module 'foo' from '/home/chiyu/foo.pyc'>,         #全局环境'__doc__': None                   }



装饰器就是闭包,但装饰器传入的参数是函数:

闭包封存上下文,这一特性可以巧妙的被用于现有函数的包装,从而为现有函数加功能。而这就是装饰器。

装饰器的原则及构成:

原则:
1、不能修改被装饰函数的源代码。
2、不能修改被装饰函数的调用方式。
3、不能改变被装饰函数的执行结果。
装饰器对被装饰函数是透明的。

在python中一切皆是对象,所以python中全部都是引用类型

因此函数可以像变量一样被指向和传递。

def diguo():
print("地锅50")
return 50
def doupi(fn):
def jia():
print("豆皮10")
return fn()+10
return jia
def xiang(fnn):
def jia():
print("香菜")
return fnn()+5
return jia
aa=doupi(xiang(diguo))
print(aa())

但是这样看起来貌似可读性就比较差了,所以在python中实现了语法糖

def doupi(fn):
    def jiadoupi():
        print("麻将豆皮10块")
        return fn()+10
    return jiadoupi
def xiangcai(fnn):
    def jiaxiangcai():
        print("麻将香菜5块")
        return fnn()+5
    return jiaxiangcai
@xiangcai
@doupi
def diguo():
    print("底锅50")
    return 50
print(x)

@后的方法名就是python自带的语法糖,为了简写也可以取到和装饰器调用一样的效果,这样的程序看起来是不是就简洁了很多

在设计模式中装饰器就如同他的名字一样把他装饰起来






猜你喜欢

转载自blog.csdn.net/qq_38262155/article/details/80641494