Python 学习笔记 装饰器 与 context

本文链接地址 http://quqiuzhu.com/2016/python-decorator-and-context

装饰器

Python中函数是一等公民,装饰器的作用就是接收一个函数,返回其增强版本的函数。例如:

def decorator(function):
    def _mydecorator(*args, **kw):
        print 'do something before'
        res = function(*args, **kw)
        print 'do somthing after'
        return res
    return _mydecorator

@decorator
def function():
    print 'function executing'

function()

输出:
do something before
function executing
do somthing after

装饰器是语法糖,因此装饰器可以用其他一般的语句来实现,我们将上面例子中的function定义部分作出下面改动

def function():
    print 'function executing'

function = decorator(function)

实现同样的功能,所以装饰器一点也不厉害,就是函数调用加上赋值运算的语法糖。

上面的是无参数的装饰器,如果是有参数的装饰器,则这么来实现

def otherdecorator(args1, args2):
    def _otherdecorator(function):
        def __otherdecorator(*args, **kw):
            print 'do something before with args %s, %s' % (args1, args2)
            res = function(*args, **kw)
            print 'do something after with args %s, %s' % (args1, args2)
            return res
        return __otherdecorator
    return _otherdecorator

@otherdecorator('name', 'age')
def function():
    print 'function executing'

function()
输出:
do something before with args name, age
function executing
do something after with args name, age

有参数的函数的定义相当于

def function():
    print 'function executing'

function = otherdecorator('name', 'age')(function)

装饰器还有类的实现方式,类实现__call__方法的时候可以被调用,这里不再多讲。

应用

  • 参数检查
  • 缓存
  • 代理

context

with 语句的使用

python 上下文跟 with 语句的使用有关。一般的用法如下

with open(filename) as f:
    for line in f:
        print line
        raise ValueError()

如果在语句体中发生异常,文件也将正常关闭,主要是因为 with 语句与 context_manager 的交互。 context_manager 是实现了 __enter__()__exit__() 方法的对象。 with 语句保证在语句体重发生异常时,__exit__() 方法 也会被调用,从而使程序正确退出上下文。

上面的代码中,open(filename) 返回的是一个 context_manager, 而 as f 这个 f 被赋值的是 context_manager.__enter__() 的返回结果。

但是有时候又会发现,不用with语句也可以直接使用,比如 f = open(filename) 。这是因为 python 的文件对象实现了 __enter__()__exit__() 方法, 文件对象本身也是 context_manager, 其 __enter__() 返回的是自身。

contextlib

有一个装饰器 contexmanager, 一个 closing() 函数和 nested() 函数。

contexmanager 是用来帮助我们自定义 contexmanager 的, 其中 yield 语句前一部分在 __enter__() 中执行,yield 语句 执行 with 语句体, yield 语句后的部分在 __exit__() 中执行。

@contextmanager
def cm():
    print 'do something before'
    yield
    print 'do something after'

很容易想出来 contextmanager 装饰器的实现方式,这里不再多讲。

closing(that) 函数是一个 contextmanager,不是装饰器,它的作用就是最终会调用 that 的 close 方法,如果不想自己实现上下文管理器,但是也要支持上下文管理器的功能的话,就只需要实现 close 方法,然后使用 with closing(that) as f 就好了。

nested() 函数用来解决嵌套with语句的问题,可以这样使用

with nested(A(), B(), C()) as (X, Y, Z):
      pass

如果细节了解不清楚,建议看 IBM 的文章

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值