Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference between Context Managers and Decorators in Python

What is the main difference between the two? I have been studying Python and came across them. A decorator is essentially a function that wraps another function and you can do anything before and after a particular function executes.

def my_decorator(some_function):
    def wrapper(*args, **kwargs):
        print("Do something before the function is called")
        some_function(*args, **kwargs)
        print("Do something after the function is called")

    return wrapper

@my_decorator
def addition(a, b):
    result = a+b
    print("Addition of {} and {} is {}".format(a,b,result))

But after studying Context Manager, I couldn't help but notice that it too has a enter and exit where you could do most similar operations.

from contextlib import contextmanager

@contextmanager
def open_file(path, mode):
    the_file = open(path, mode)
    yield the_file
    the_file.close()

files = []

for x in range(100000):
    with open_file('foo.txt', 'w') as infile:
        files.append(infile)

for f in files:
    if not f.closed:
        print('not closed')

Everything before yield is taken as part of the "enter" and everything after a part of "exit".

Although both Context Managers and Decorators are syntactically different, their behaviors can be looked upon as similar. So what is the difference? What are the different scenarios when one should use either of them?

like image 673
Mithil Bhoras Avatar asked Jun 12 '18 18:06

Mithil Bhoras


2 Answers

They are completely separate concepts and should not be seen in the same light.

A decorator lets you augment or replace a function or a class when it is defined. This is far broader than just executing things before or after a function call. Sure, your specific decorator lets you do something just before and after a function call, provided no exception is raised, or you explicitly handle exceptions. But you could also use a decorator to add an attribute to the function object, or to update some kind of registry. Or to return something entirely different and ignore the original function. Or to produce a wrapper that manipulates the arguments passed in, or the return value of the original function. A context manager can't do any of those things.

A context manager on the other hand lets you abstract away try: ... finally: constructs, in that no matter how the block exits, you get to execute some more code at the end of the block. Even if the block raises an exception, or uses return to exit a function, the context manager __exit__ method is still going to be called, regardless. A context manager can even suppress any exceptions raised in the block.

The two concepts are otherwise not related at all. Use decorators when you require to do something to or with functions or classes when they are defined. Use context managers when you want to clean up or take other actions after a block ends.

like image 65
Martijn Pieters Avatar answered Sep 24 '22 04:09

Martijn Pieters


they are completely different concepts.

context managers are objects to be used with the python with keyword. It runs code when entering the block and exiting the block.

decorators are modifications to a function or class definition. It runs code that replaces the function as it is being defined.

@D
def Y(...):
    ...

is just another way of writing

def Y(...):
    ....
Y = D(Y)
like image 34
nosklo Avatar answered Sep 22 '22 04:09

nosklo