python closures and decorators

Functions as objects and closures

python中的函数是first-class objects,即它们可以作为参数传递到其他函数中,可以存储到数据结构中,也可以作为函数的返回值

一个简单例子

# foo.py
def callf(func):
    return func()
>>> import foo
>>> def hello():
...     return ‘hello‘
...
>>> f = foo.callf(hello) # function as an arg
>>> f
‘hello‘

对上面代码做一点修改:

# foo.py
x = 42
def callf(func):
    return func()
>>> import foo
>>> x = 37
>>> def hello():
...     return ‘hello. x is %d‘ % x
...
>>> foo.callf(hello)
‘hello. x is 37‘

这里我们调用foo.callf(),但是x的值却不是foo.py中定义的变量值,而是调用函数前上文的值。因此我们应该关注一个函数与周边变量的关系,也就有了closure闭包的概念

closure: 当一个函数的语句和它们所执行的环境一起打包的时候,就成为了所谓的closure 我们可以查看一个函数的__globals__属性,如:

>>> hello.__globals__
{‘__builtins__‘: <module ‘__builtin__‘ (built-in)>,
‘helloworld‘: <function helloworld at 0x7bb30>,
‘x‘: 37, ‘__name__‘: ‘__main__‘, ‘__doc__‘: None
‘foo‘: <module ‘foo‘ from ‘foo.py‘>}

可以看到hello里面已经绑定了x=37

当使用嵌套函数时,闭包会给inner function捕获执行需要的环境,如

import foo
def bar():
    x = 13
    def helloworld():
        return "Hello World. x is %d" % x
    foo.callf(helloworld) # returns ‘Hello World, x is 13‘

这里内部函数helloworld与x=13已经组成一个闭包

闭包可以怎样使用?我们看一个延时赋值的例子:

from urllib import urlopen
def page(url):
    def get():
        return urlopen(url).read()
    return get
>>> python = page("http://www.python.org")
>>> python
<function get at 0x95d5f0>
>>> pydata = python() # fetch http://www.python.org
>>> pydata.__closure__
(<cell at 0x67f50: str object at 0x69230>,)
>>> python._ _closure_ _[0].cell_contents
‘http://www.python.org‘

pydata对象在赋值的时候已经绑定了参数url的值,可以留到以后进行调用

Decorators

decorator装饰器的作用是在里面封装其他函数或者类,用@号来表示,eg:

@trace
def square(x):
    return x*x

等同于

def square(x):
    return x*x
square = trace(square)

这个例子中定义了一个square()函数,但马上将它作为参数传递到trace()中,并将返回的对象替代原来的square。装饰器顾名思义就是给原来函数增加一些装饰,比如我们这里trace函数可以做一些额外的事情,最后返回的对象可以是一个包含square的函数,即对我们的square函数做了“装饰”

再看一个平常使用的例子:

enable_tracing = True
if enable_tracing:
    debug_log = open("debug.log","w")

def trace(func):
    if enable_tracing:
        def callf(*args,**kwargs):
            debug_log.write("Calling %s: %s, %s\n" % (func._ _name_ _, args, kwargs))
            r = func(*args,**kwargs)
            debug_log.write("%s returned %s\n" % (func._ _name, r))
            return r
        return callf
    else:
        return func

这个代码就可以追踪上面square函数的调用,如果enable_tracing,则用函数callf将func封装起来,在里面增加记录日志功能,并且callf最后还是返回func函数,也就是说如果允许追踪的时候我们就将原来的函数对象装饰成一个有追踪功能的callf函数对象返回,如果不允许追踪,就简单返回func本身,这是非常精妙的一种设计

时间: 2024-10-21 04:50:03

python closures and decorators的相关文章

Python高级特性(2):Closures、Decorators和functools(转)

原文:Python高级特性(2):Closures.Decorators和functools 装饰器(Decorators) 装饰器是这样一种设计模式:如果一个类希望添加其他类的一些功能,而不希望通过继承或是直接修改源代码实现,那么可以使用装饰器模式.简单来说 Python中的装饰器就是指某些函数或其他可调用对象,以函数或类作为可选输入参数,然后返回函数或类的形式.通过这个在Python2.6版本中被新 加入的特性可以用来实现装饰器设计模式. 顺便提一句,在继续阅读之前,如果你对Python中的

python装饰器Decorators

http://blog.csdn.net/pipisorry/article/details/41902599 Introduction 装饰器Decorators是一个很著名的设计模式,经常被用于有切面需求的场景,较为经典的有插入日志.性能测试.事务处理等.装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量函数中与函数功能本身无关的雷同代码并继续重用.概括的讲,装饰器的作用就是为已经存在的对象添加额外的功能.装饰器用于在不改变原函数代码的情况下修改已存在的函数.常见场景是增加一句

Python高级特性(3): Classes和Metaclasses(转)

原文:Python高级特性(3): Classes和Metaclasses 类和对象 类和函数一样都是Python中的对象.当一个类定义完成之后,Python将创建一个“类对象”并将其赋值给一个同名变量.类是type类型的对象(是不是有点拗口?). 类对象是可调用的(callable,实现了 __call__方法),并且调用它能够创建类的对象.你可以将类当做其他对象那么处理.例如,你能够给它们的属性赋值,你能够将它们赋值给一个变量,你 可以在任何可调用对象能够用的地方使用它们,比如在一个map中

(转)详解Python闭包

Closures In Python Entirely copied from here All I want is to mark it, thanks for this nice article. You might have lived a long and happy coding life without ever needing to know what closures are. For one, many languages like C or C++ don't even su

Pythonの坑

Python closures and late binding A closure occurs when a function has access to a local variable from an enclosing scope that has finished its execution. def make_printer(msg): def printer(): print msg return printer We can see that the printer() fun

Python 函数装饰器入门

原文链接: --> A guide to Python's function decorators Python功能强劲,语法表现力强,尤其装饰器深深的吸引着我.在设计模式中,装饰器可以在不使用子类的情况下,动态的改变函数,方法以及类的功能.这个功能非常有用,特别在你想扩展函数的功能同时又不想改变原有的函数.的确,我们任意的实现装饰器设计模式,但是,python通过提供简单的语法和特性让装饰器的实现变的如此简单. 在本文中,我将用一组例子来深入浅入python 函数装饰器的功能,所有的例子都是在

python上下文管理器ContextLib及with语句

http://blog.csdn.net/pipisorry/article/details/50444736 with语句 with语句是从 Python 2.5 开始引入的一种与异常处理相关的功能(2.5 版本中要通过 from __future__ import with_statement 导入后才可以使用),从 2.6 版本开始缺省可用(参考 What's new in Python 2.6? 中 with 语句相关部分介绍).with 语句适用于对资源进行访问的场合,确保不管使用过程

python天天美味

Python中的splitlines用来分割行.当传入的参数为True时,表示保留换行符 \n.通过下面的例子就很明白了: 基本语法:S.splitlines(keepends=False) -> list of strings mulLine = """Hello!!! Wellcome to Python's world!    There are a lot of interesting things!        Enjoy yourself. Thank y

闭包结构的本质

闭包定义: 如果在一个内部函数里,对在外部作用域(但不是在全局作用域)的变量进行引用,那么内部函数就被认为是闭包; 闭包的概念:闭包(Closure)是词法闭包(Lexical Closure)的简称,是引用了自由变量的函数.这个被引用的自由变量将和这个函数一同存在,即使已经离开了创造它的环境也不例外.所以,闭包是由函数和与其相关的引用环境组合而成的实体. 采用比较说法就是,通常一个函数运行结束之后,内部变量就会被销毁释放,C就是这样:然而在闭包这种结构中,外部函数的局部变量在该函数运行之后,其