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


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

decorators and closures

Started byAndrea Crotti <andrea.crotti.0@gmail.com>
First post2011-11-21 14:44 +0000
Last post2011-11-22 09:03 -0800
Articles 4 — 3 participants

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


Contents

  decorators and closures Andrea Crotti <andrea.crotti.0@gmail.com> - 2011-11-21 14:44 +0000
    Re: decorators and closures Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2011-11-22 03:54 +0000
    Re: decorators and closures 88888 Dihedral <dihedral88888@googlemail.com> - 2011-11-22 09:03 -0800
    Re: decorators and closures 88888 Dihedral <dihedral88888@googlemail.com> - 2011-11-22 09:03 -0800

#16012 — decorators and closures

FromAndrea Crotti <andrea.crotti.0@gmail.com>
Date2011-11-21 14:44 +0000
Subjectdecorators and closures
Message-ID<mailman.2903.1321886678.27778.python-list@python.org>
With one colleague I discovered that the decorator code is always 
executed, every time I call
a nested function:

def dec(fn):
     print("In decorator")
     def _dec():
         fn()

     return _dec

def nested():
     @dec
     def fun():
         print("here")

nested()
nested()

Will give:
In decorator
In decorator

So we were wondering, would the interpreter be able to optimize this 
somehow?
I was betting it's not possible, but I'm I would like to be wrong :)

[toc] | [next] | [standalone]


#16069

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2011-11-22 03:54 +0000
Message-ID<4ecb1d03$0$30003$c3e8da3$5496439d@news.astraweb.com>
In reply to#16012
On Mon, 21 Nov 2011 14:44:34 +0000, Andrea Crotti wrote:

> With one colleague I discovered that the decorator code is always
> executed, every time I call a nested function:

"def" is a statement which is executed at runtime. Often people will talk 
about "definition time" instead of "compile time".

Python compiles your source into byte code (compile time), then executes 
the byte code. The function doesn't actually get created until the byte 
code is executed, i.e. at run time. This is not as slow as it sounds, 
because the function is created from pre-compiled parts.

In effect, if you have a module:

x = 23
def spam(a):
    print x
    print x+1
    return x**3


then the body of the function is compiled into a "code object" at compile 
time, and at runtime the function object itself is assembled from the 
code object, name, and whatever other bits and pieces are needed. In 
pseudo-code, the byte code looks like this:

bind name "x" to object 23
build a function object "spam" from code object
bind name "spam" to function object

The hard part is creating the code object, as that requires parsing the 
source code of the body and generating byte code. That's done once, ahead 
of time, so the actual "build a function" part is fast.

Now, if you have an ordinary nested function:

def spam(a):
    def ham(b):
        return a+b
    return ham(a+42)  # returns a numeric value

or a closure:

def spam(a):
    def ham(b):
        return a+b
    return ham  # returns a closure (function object)

the process is no different: the inner function doesn't get created until 
runtime, that is, when spam gets *called*. But it gets created from parts 
that were prepared earlier at compile time, and so is fast.

Add a decorator, and the basic process remains. Remember that decorator 
syntax is just syntactic sugar. This:

@decorator
def spam():
    pass

is exactly the same as this:

def spam():
    pass

spam = decorator(spam)

which clearly has to be done at runtime, not compile time. That applies 
regardless of whether the function is nested or top-level.



-- 
Steven

[toc] | [prev] | [next] | [standalone]


#16080

From88888 Dihedral <dihedral88888@googlemail.com>
Date2011-11-22 09:03 -0800
Message-ID<24059779.511.1321981422154.JavaMail.geo-discussion-forums@prou19>
In reply to#16012
On Monday, November 21, 2011 10:44:34 PM UTC+8, Andrea Crotti wrote:
> With one colleague I discovered that the decorator code is always 
> executed, every time I call
> a nested function:
> 
> def dec(fn):
>      print("In decorator")
>      def _dec():
>          fn()
> 
>      return _dec
> 
> def nested():
>      @dec
>      def fun():
>          print("here")
> 
> nested()
> nested()
> 
> Will give:
> In decorator
> In decorator
> 
> So we were wondering, would the interpreter be able to optimize this 
> somehow?
> I was betting it's not possible, but I'm I would like to be wrong :)

I love to use decorators. I did the same things to  functions and structures in c long time ago. I think that  might be  the dark night era in  programming  in the early 90's long long ago. 

Cheers.   

[toc] | [prev] | [next] | [standalone]


#16081

From88888 Dihedral <dihedral88888@googlemail.com>
Date2011-11-22 09:03 -0800
Message-ID<mailman.2951.1321981431.27778.python-list@python.org>
In reply to#16012
On Monday, November 21, 2011 10:44:34 PM UTC+8, Andrea Crotti wrote:
> With one colleague I discovered that the decorator code is always 
> executed, every time I call
> a nested function:
> 
> def dec(fn):
>      print("In decorator")
>      def _dec():
>          fn()
> 
>      return _dec
> 
> def nested():
>      @dec
>      def fun():
>          print("here")
> 
> nested()
> nested()
> 
> Will give:
> In decorator
> In decorator
> 
> So we were wondering, would the interpreter be able to optimize this 
> somehow?
> I was betting it's not possible, but I'm I would like to be wrong :)

I love to use decorators. I did the same things to  functions and structures in c long time ago. I think that  might be  the dark night era in  programming  in the early 90's long long ago. 

Cheers.   

[toc] | [prev] | [standalone]


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


csiph-web