所谓闭包,就是将组成函数的语句和这些语句的执行环境打包在一起时,得到的对象:
听上去的确有些复杂,还是用一个栗子来帮助理解一下。假设我们在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自带的语法糖,为了简写也可以取到和装饰器调用一样的效果,这样的程序看起来是不是就简洁了很多
在设计模式中装饰器就如同他的名字一样把他装饰起来