What Is The Biggest Advantage Of The Decorator In Python?

Asked 3 months ago
Answer 1
Viewed 177
1

Python decorators are so natural to utilize. Any individual who knows how to compose a Python capability can figure out how to utilize a decorator:

@somedecorator
def some_function():
    print("Check it out, I'm using decorators!")

In any case, composing decorators is something else entirely set. Furthermore, it's not trifling; you need to comprehend:

closures
step by step instructions to work with capabilities as top notch contentions
variable contentions
contention unloading, even
a few subtleties of how Python stacks its source code.
This all requires some investment to comprehend and dominate. Furthermore, you as of now have an excess of things to learn. Is this value your time?

For my purposes, the response has been "multiple times, YES!" And chances are it will be for you, as well. What are the critical advantages of composing decorators… what they let you do effectively and capably, in your everyday turn of events?

Examination, logging, and instrumentation

Particularly with huge applications, we frequently need to explicitly gauge what's happening, and record measurements that evaluate various exercises. By embodying such critical occasions in their own capability or technique, a decorator can deal with this prerequisite discernibly and without any problem.

from myapp.log import logger

def log_order_event(func):
    def wrapper(*args, **kwargs):
        logger.info("Ordering: %s", func.__name__)
        order = func(*args, **kwargs)
        logger.debug("Order result: %s", order.result)
        return order
    return wrapper

@log_order_event
def order_pizza(*toppings):
    # let's get some pizza!

A similar methodology can be utilized to record counts or different measurements.

Validation and runtime checks

Python's sort framework is specifically, yet extremely unique. For every one of its advantages, this implies a few bugs can attempt to sneak in, which more statically composed dialects (like Java) would get at gather time. That's what looking past even, you might need to uphold more complex, custom keeps an eye on information going in or out. Decorators can allow you effectively to deal with all of this, and apply it to many capabilities on the double.

Envision this: you have a bunch of capabilities, each returning a word reference, which (among different fields) incorporates a field called "rundown." The worth of this synopsis should not be in excess of 80 characters in length; assuming that disregarded, that is a mistake. Here is a decorator that raises a ValueError assuming that occurs:

def validate_summary(func):
    def wrapper(*args, **kwargs):
        data = func(*args, **kwargs)
        if len(data["summary"]) > 80:
            raise ValueError("Summary too long")
        return data
    return wrapper

@validate_summary
def fetch_customer_data():
    # ...

@validate_summary
def query_orders(criteria):
    # ...

@validate_summary
def create_invoice(params):
    # ...

Creating frameworks

When you ace composing decorators, you'll have the option to profit from the straightforward linguistic structure of utilizing them, which allows you to add semantics to the language that are not difficult to utilize. It's the following best thing to having the option to broaden the language structure of Python itself.

Numerous famous open source structures utilize this, truth be told. The webapp system Cup utilizes it to course URLs to capabilities that handle the HTTP demand:

# For a RESTful todo-list API.
@app.route("/tasks/", methods=["GET"])
def get_all_tasks():
    tasks = app.store.get_all_tasks()
    return make_response(json.dumps(tasks), 200)

@app.route("/tasks/", methods=["POST"])
def create_task():
    payload = request.get_json(force=True)
    task_id = app.store.create_task(
        summary = payload["summary"],
        description = payload["description"],
    )
    task_info = {"id": task_id}
    return make_response(json.dumps(task_info), 201)

@app.route("/tasks/<int:task_id>/")
def task_details(task_id):
    task_info = app.store.task_details(task_id)
    if task_info is None:
        return make_response("", 404)
    return json.dumps(task_info)

Here you have a worldwide item called application, with a strategy called course, taking specific contentions. That course strategy returns a decorator that is applied to the controller capability. What's happening underneath the hood is really many-sided and confounded, yet according to the viewpoint of the individual utilizing Carafe, all that intricacy is totally covered up.

Involving decorators in this manner additionally appears in stock Python. For instance, completely utilizing the item framework depends on the classmethod and property decorators:

class WeatherSimulation:
    def __init__(self, **params):
         self.params = params

    @classmethod
    def for_winter(cls, **other_params):
        params = {'month': 'Jan', 'temp': '0'}
        params.update(other_params)
        return cls(**params)

    @property
    def progress(self):
        return self.completed_iterations() / self.total_iterations()

This class has three distinct def proclamations. However, their semantics are unique:

the constructor is a typical technique
for_winter is a classmethod giving a sort of production line, and
progress is perused just, powerful trait
The straightforwardness of the @classmethod and @property decorators makes it simple to expand Python's article semantics in regular use.

Reusing impossible-to-reuse code

Python gives you a few exceptionally incredible assets for embodying code into an effectively reusable structure, with an expressive capability grammar, practical programming support, and an unlimited item framework. In any case, there are a few examples of code reuse which can't be caught by these by themselves.

Think about working with a flakey Programming interface. You make solicitations to something that speaks JSON over HTTP, and it works accurately 99.9% of the time. Yet, a little part, everything being equal, will make the server return an inner blunder, and you want to retry the solicitation. All things considered, you'd execute some retry rationale, as so:

Answered 3 months ago Tove Svendson