декоратор в Python - это то же самое, что вызов функции в функции? - PullRequest
3 голосов
/ 19 июня 2010

Я думал, что делает

@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 голосов
/ 19 июня 2010

Да, декоратор точно такой же, как вызов функции и присвоение возвращаемого значения

В этом случае возникает ошибка, потому что вы не вызываете функцию, поэтому правильный код будет

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__'
...