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


Groups > comp.lang.python > #12329

Re: Why do closures do this?

Path csiph.com!x330-a1.tempe.blueboxinc.net!usenet.pasdenom.info!aioe.org!feeder.news-service.com!multikabel.net!newsfeed10.multikabel.net!feeder2.cambriumusenet.nl!feed.tweaknews.nl!194.109.133.85.MISMATCH!newsfeed.xs4all.nl!newsfeed6.news.xs4all.nl!xs4all!post.news.xs4all.nl!not-for-mail
Return-Path <python-python-list@m.gmane.org>
X-Original-To python-list@python.org
Delivered-To python-list@mail.python.org
X-Spam-Status OK 0.002
X-Spam-Evidence '*H*': 1.00; '*S*': 0.00; 'thread,': 0.04; 'received:verizon.net': 0.07; 'terry': 0.07; '"default': 0.09; 'function:': 0.09; 'received:80.91': 0.09; 'received:80.91.229': 0.09; 'received:80.91.229.12': 0.09; 'received:gmane.org': 0.09; 'received:list': 0.09; 'received:lo.gmane.org': 0.09; 'def': 0.15; '"f"': 0.16; '"n"': 0.16; 'closure.': 0.16; 'closures': 0.16; 'closures,': 0.16; 'declaration': 0.16; 'expression,': 0.16; 'preserved': 0.16; 'reedy': 0.16; 'this:': 0.16; 'wrote:': 0.16; 'upgraded': 0.18; 'jan': 0.19; 'seems': 0.20; 'tells': 0.21; 'header:In-Reply-To:1': 0.22; 'refers': 0.23; 'pm,': 0.24; 'explains': 0.24; 'code': 0.25; "i'm": 0.27; 'function': 0.27; 'bound': 0.29; 'constant': 0.29; 'definition': 0.30; 'remains': 0.30; 'returns,': 0.30; 'subject:?': 0.31; 'least': 0.31; 'values': 0.32; 'capture': 0.32; 'value.': 0.32; 'there': 0.33; 'to:addr:python-list': 0.33; "i've": 0.34; 'header:User-Agent:1': 0.34; 'surprised': 0.34; 'header:X-Complaints-To:1': 0.35; 'google': 0.36; 'question': 0.36; 'using': 0.37; 'but': 0.37; 'two': 0.37; 'received:org': 0.38; 'somewhat': 0.38; 'subject:: ': 0.39; 'ways': 0.39; 'header:Mime-Version:1': 0.39; 'either': 0.39; 'needed.': 0.39; 'to:addr:python.org': 0.39; "it's": 0.40; 'your': 0.61; 'john': 0.62; 'factory': 0.73; 'subject:this': 0.74; '11:45': 0.84; 'idiom': 0.84; 'locals': 0.84; 'returns.': 0.84; 'right),': 0.84; 'surprised,': 0.84; 'time"': 0.84; 'tricky': 0.84
X-Injected-Via-Gmane http://gmane.org/
To python-list@python.org
From Terry Reedy <tjreedy@udel.edu>
Subject Re: Why do closures do this?
Date Sun, 28 Aug 2011 00:19:07 -0400
References <20110828134505.795cd32b8fc5ccc472f85ae3@johnohagan.com>
Mime-Version 1.0
Content-Type text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding 7bit
X-Gmane-NNTP-Posting-Host pool-74-109-121-73.phlapa.fios.verizon.net
User-Agent Mozilla/5.0 (Windows NT 6.1; WOW64; rv:6.0) Gecko/20110812 Thunderbird/6.0
In-Reply-To <20110828134505.795cd32b8fc5ccc472f85ae3@johnohagan.com>
X-BeenThere python-list@python.org
X-Mailman-Version 2.1.12
Precedence list
List-Id General discussion list for the Python programming language <python-list.python.org>
List-Unsubscribe <http://mail.python.org/mailman/options/python-list>, <mailto:python-list-request@python.org?subject=unsubscribe>
List-Archive <http://mail.python.org/pipermail/python-list>
List-Post <mailto:python-list@python.org>
List-Help <mailto:python-list-request@python.org?subject=help>
List-Subscribe <http://mail.python.org/mailman/listinfo/python-list>, <mailto:python-list-request@python.org?subject=subscribe>
Newsgroups comp.lang.python
Message-ID <mailman.501.1314505201.27778.python-list@python.org> (permalink)
Lines 59
NNTP-Posting-Host 2001:888:2000:d::a6
X-Trace 1314505201 news.xs4all.nl 2517 [2001:888:2000:d::a6]:51346
X-Complaints-To abuse@xs4all.nl
Xref x330-a1.tempe.blueboxinc.net comp.lang.python:12329

Show key headers only | View raw


On 8/27/2011 11:45 PM, John O'Hagan wrote:
> Somewhat apropos of the recent "function principle" thread, I was recently surprised by this:
>
> funcs=[]
> for n in range(3):
>      def f():
>          return n
>      funcs.append(f)
>
>
>
> The last expression, IMO surprisingly, is [2,2,2], not [0,1,2]. Google tells me I'm not the only one surprised, but explains that it's because "n" in the function "f" refers to whatever "n" is currently bound to, not what it was bound to at definition time (if I've got that right), and that there are at least two ways around it: either make a factory function:

def f(): return n
is a CONSTANT value. It is not a closure.

Your code above is the same as
def f(): return n
funcs = [f,f,f]
n = 2
[i() for i in funcs]

> def mkfnc(n):
>      def fnc():
>          return n
>      return fnc

fnc is a closure and n in a nonlocal name. Since you only read it, no 
nonlocal declaration is needed.

> funcs=[]
> for n in range(3):
>      funcs.append(mkfnc(n))
>
> which seems roundabout, or take advantage of the "default values set at definition time" behaviour:
>
> funcs=[]
> for n in range(3):
>      def f(n=n):
>          return n
>      funcs.append(f)
>
> which seems obscure, and a side-effect.

It was the standard idiom until nested functions were upgraded to 
enclose or capture the values of nonlocals.

> My question is, is this an inescapable consequence of using closures,

I cannot answer since I am not sure what you mean by 'this'.
Closures are nested functions that access the locals of enclosing 
functions. To ensure that the access remains possible even after the 
enclosing function returns, the last value of such accessed names is 
preserved even after the enclosing function returns. (That is the tricky 
part.)

-- 
Terry Jan Reedy

Back to comp.lang.python | Previous | NextNext in thread | Find similar | Unroll thread


Thread

Re: Why do closures do this? Terry Reedy <tjreedy@udel.edu> - 2011-08-28 00:19 -0400
  Re: Why do closures do this? John Nagle <nagle@animats.com> - 2011-09-16 13:50 -0700

csiph-web