Easy understanding decorators

If you used Django for any length of time, you would have come across the loginrequired decorator. You write @loginrequired before a view, and it magically becomes accessible only to authenticated users.

Decorators were introduced in python 2.4. PEP 318 is the PEP describing it. At the simplest decorators are nothing but callables returning other callables, and the decorator syntax @decorator is nothing but foo = bar(foo), where both bar and foo are callables.

Let us see some decorators in action.

def good_function(): print 'I am a good function'

def decorator(origfunc): def badfunc(): print 'I am a bad function' return bad_func

In [3]: goodfunction = decorator(goodfunction)

In [4]: good_function() I am a bad function

@decorator def good_function2(): print 'I am a good function'

In [6]: good_function2() I am a bad function

So you can see that the decorated function depended only on the value of the function returned by the decorator.

Here we discarded the function we were passed. Any useful decorator, decorates the original function, so it would use the original function. Let us see an actual decorator which may be useful.

def isvalpositivedeco(origfunc): def tempfunc(val): if val < 0: return 0 else: return origfunc(val) return temp_func

@isvalpositive_deco
def sqrt(val): import math return math.pow(val, (1.0/2))

print sqrt(-1) print sqrt(4)

Here we defined an decorator isvalpositive_deco which will make functions return 0, if the argument passed is negative. We can use this decorator to guard against MathErrors. Class based decorators

Decorators are just callables, and hence can be a class which has call method. Sometimes they are easier to understand and reason about(than decorators written as functions). Lets see one,

class LogArgumentsDecorator(object): def init(self, origfunc): self.origfunc = origfunc print 'started logging: %s' % origfunc.name

    def __call__(self,  *args, **kwargs):
            print 'args: %s' % args
            print 'kwargs:%s'% kwargs
            return self.orig_func(*args, **kwargs)

@LogArgumentsDecorator
def sumofsquares(a, b): return aa + bb

print sumofsquares(3, b=4)

This outputs,

started logging: sumofsquares args: 3 kwargs:{'b': 4} 25

Lets see what happens when we do,

@LogArgumentsDecorator
def sumofsquares(a, b):

This is equivalent to

sumofsquares = LogArgumentsDecorator(sumofsquares)

At this point, we created a new LogArgumentsDecorator object, so LogArgumentsDecorator.init(self, sumofsquares) gets called. Hence print 'started logging: %s' % orig_func.name line is executed.

When we do sumofsquares(...)

LogArgumentsDecorator.call gets called with the passed values, where we print the arguments and call the original function.

Here is one more example of a class based decorator. Here we rewrite(sort of, anyway) Django's login_required decorator as a class based decorator.

class LoginRequiredDecorator(object): def init(self, origfunc): self.origfunc = orig_func

def call(self, request, args, *kwargs): if request.user.isauthenticated(): self.origfunc(request, args, *kwargs) else: return HttpResponseRedirect(reverse('...'))

Similar to above, it takes the view function, during init. When the request comes, call makes sure that user is authenticated, and takes action appropriately.

Resources Decorator Library Pep 318

Thank you

inspried from https://agiliq.com/blog/2009/06/understanding-decorators/

#ComputerScience #Python

Note by Aravind Arvnd
6 years, 3 months ago

No vote yet
1 vote

  Easy Math Editor

This discussion board is a place to discuss our Daily Challenges and the math and science related to those challenges. Explanations are more than just a solution — they should explain the steps and thinking strategies that you used to obtain the solution. Comments should further the discussion of math and science.

When posting on Brilliant:

  • Use the emojis to react to an explanation, whether you're congratulating a job well done , or just really confused .
  • Ask specific questions about the challenge or the steps in somebody's explanation. Well-posed questions can add a lot to the discussion, but posting "I don't understand!" doesn't help anyone.
  • Try to contribute something new to the discussion, whether it is an extension, generalization or other idea related to the challenge.
  • Stay on topic — we're all here to learn more about math and science, not to hear about your favorite get-rich-quick scheme or current world events.

MarkdownAppears as
*italics* or _italics_ italics
**bold** or __bold__ bold

- bulleted
- list

  • bulleted
  • list

1. numbered
2. list

  1. numbered
  2. list
Note: you must add a full line of space before and after lists for them to show up correctly
paragraph 1

paragraph 2

paragraph 1

paragraph 2

[example link](https://brilliant.org)example link
> This is a quote
This is a quote
    # I indented these lines
    # 4 spaces, and now they show
    # up as a code block.

    print "hello world"
# I indented these lines
# 4 spaces, and now they show
# up as a code block.

print "hello world"
MathAppears as
Remember to wrap math in \( ... \) or \[ ... \] to ensure proper formatting.
2 \times 3 2×3 2 \times 3
2^{34} 234 2^{34}
a_{i-1} ai1 a_{i-1}
\frac{2}{3} 23 \frac{2}{3}
\sqrt{2} 2 \sqrt{2}
\sum_{i=1}^3 i=13 \sum_{i=1}^3
\sin \theta sinθ \sin \theta
\boxed{123} 123 \boxed{123}

Comments

There are no comments in this discussion.

×

Problem Loading...

Note Loading...

Set Loading...