Is a decorator in python exactly the same as calling a function on a function?

I thought what to do

@f
def g():
   print 'hello'

exactly matches

def g():
   print 'hello'
g=f(g)

But I had this code that uses contextlib.contextmanager:

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

which works and gives 1 3 2

And when I tried to change it to

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

I get AttributeError: 'function' object has no attribute '__exit__'

What am I missing? Is there any kind of black magic specially in contextlib.contextmanager, or am I misunderstanding how decorators in general work?

+3
source share
1 answer

Yes, the decorator is exactly the same as calling a function and assigning a return value

In this case, the error occurs because you are not calling the function, so the correct code will be

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__'
+5

Source: https://habr.com/ru/post/1750786/


All Articles