Python中的装饰器是否与对函数进行函数调用完全相同?
我原以为这样做
@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 个回答
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__'