Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #37975 > unrolled thread

Re: confusion with decorators

Started byDave Angel <davea@davea.name>
First post2013-01-30 20:12 -0500
Last post2013-02-04 10:19 +0000
Articles 2 — 2 participants

Back to article view | Back to comp.lang.python

This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by below is the oldest one visible, not the original post.


Contents

  Re: confusion with decorators Dave Angel <davea@davea.name> - 2013-01-30 20:12 -0500
    Re: confusion with decorators Duncan Booth <duncan.booth@invalid.invalid> - 2013-02-04 10:19 +0000

#37975 — Re: confusion with decorators

FromDave Angel <davea@davea.name>
Date2013-01-30 20:12 -0500
SubjectRe: confusion with decorators
Message-ID<mailman.1240.1359594784.2939.python-list@python.org>
On 01/30/2013 07:34 PM, Jason Swails wrote:
> Hello,
>
> I was having some trouble understanding decorators and inheritance and all
> that.  This is what I was trying to do:
>
> # untested
> class A(object):
>     def _protector_decorator(fcn):
>        def newfcn(self, *args, **kwargs):
>           return fcn(self, *args, **kwargs)
>        return newfcn
>
>     @_protector_decorator
>     def my_method(self, *args, **kwargs):
>        """ do something here """
>
> class B(A):
>     def _protector_decorator(fcn):
>        def newfcn(self, *args, **kwargs):
>           raise MyException('I do not want B to be able to access the
> protected functions')
>        return newfcn
>
> The goal of all that was to be able to change the behavior of my_method
> inside class B simply by redefining the decorator. Basically, what I want
> is B.my_method() to be decorated by B._protector_decorator, but in the code
> I'm running it's decorated by A._protector_decorator.
>
> I presume this is because once the decorator is applied to my_method in
> class A, A.my_method is immediately bound to the new, 'decorated' function,
> which is subsequently inherited (and not decorated, obviously), by B.
>
> Am I correct here?  My workaround was to simply copy the method from class
> A to class B, after which B._protector_decorator decorated the methods in
> B.  While this doesn't make the use of decorators completely pointless (the
> decorators actually do something in each class, it's just different), it
> does add a bunch of code duplication which I was at one point hopeful to
> avoid.
>
> I'm still stumbling around with decorators a little, but this exercise has
> made them a lot clearer to me.
>
>

I'm certainly not the expert on decorators;  I've only used them for 
simple things.  But I think I can clear up one misconception.

The decorator function will execute while *compiling* the class A, and 
the one in class B is unreferenced.

The decorator @_protector_decorator is shorthand for something like
    mymethod = _protector_decorator(mymethod)

So by the time the compiler ends with class A, the mymethod has its 
final value.

(Note, I've not used a decorator that was defined inside a class, so I'm 
probably missing the appropriate A. or self. or cls. overrides.)
But the order of definition is still correct.  A decorator executes 
once, just after a function is completed.



-- 
DaveA

[toc] | [next] | [standalone]


#38118

FromDuncan Booth <duncan.booth@invalid.invalid>
Date2013-02-04 10:19 +0000
Message-ID<XnsA15D69058A1D2duncanbooth@127.0.0.1>
In reply to#37975
Dave Angel <davea@davea.name> wrote:

> The decorator function will execute while *compiling* the class A, and 
> the one in class B is unreferenced.

No, the decorator function is called when *executing* the class body of A. 
Compilation could have happened weeks earlier.

It really does make it a lot easier to understand this sort of issue if you 
remember that 'class' and 'def' are simply executable statements: the body 
of 'class' executes as part of the class definition whenever normal 
execution reaches the 'class' statement, the body of 'def' doesn't execute 
until the function is called (but default arguments are evaluated when the 
'def' is executed).

In both cases however the code is fully compiled whenever the module is 
compiled: that could be when the module is imported or if it is __main__ 
when the script executes, but after the first run of the program all of the 
modules (nto the script) will have been compiled once and don't compile 
again until the source changes.

-- 
Duncan Booth http://kupuguy.blogspot.com

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.python


csiph-web