python中的装饰器与调用函数的函数完全相同吗?

时间:2010-06-19 07:02:09

标签: python decorator contextmanager

我以为在做

@f
def g():
   print 'hello'

完全相同
def g():
   print 'hello'
g=f(g)

但是,我有这个代码,它使用contextlib.contextmanager:

@contextlib.contextmanager
def f():
    print 1
    yield
    print 2
with f:
    print 3

有效并产生1 3 2

当我试图将其改为

def f():
    print 1
    yield
    print 2
f=contextlib.contextmanager(f)
with f:
    print 3

我得到AttributeError: 'function' object has no attribute '__exit__'

我错过了什么?在contextlib.contextmanager中是否有一些黑魔法,或者我是否误解了装饰器的工作原理?

1 个答案:

答案 0 :(得分:5)

是的,装饰器与调用函数和分配返回值完全相同

在这种情况下出现错误是因为你没有调用函数,因此正确的代码将是

def f():
    print 1
    yield
    print 2

f=contextlib.contextmanager(f)
with f():
    print 3

我也不确定你是否测试了代码,因为你给出的装饰器代码会因同样的原因而失败

@contextlib.contextmanager
def f():
    print 1
    yield
    print 2
with f:
    print 3

错误:

    with f:
AttributeError: 'function' object has no attribute '__exit__'