Is there a way to change the closure of a python function?

Terry Reedy tjreedy at udel.edu
Tue Sep 27 17:19:02 EDT 2016


On 9/27/2016 11:01 AM, Chris Angelico wrote:
> On Wed, Sep 28, 2016 at 12:01 AM, Peng Yu <pengyu.ut at gmail.com> wrote:
>> Hi, In many other functional language, one can change the closure of a
>> function. Is it possible in python?
>>
>> http://ynniv.com/blog/2007/08/closures-in-python.html
>>
>
> From the blog post:
>
> """In some languages, the variable bindings contained in a closure
> behave just like any other variables. Alas, in python they are
> read-only."""
>
> This is not true, at least as of Python 3.
>
> def makeInc(x):
>   def inc(y, moreinc=0):
>      # x is "closed" in the definition of inc
>      nonlocal x
>      x += moreinc
>      return y + x
>   return inc

The value of the cell variable is writable from within the body of the 
closure function if declared nonlocal, but not otherwise, and not from 
without.  The latter may be what Peng meant by 'change' and the blogger 
by 'read-only'.

def makeInc(x):
   def inc(y, moreinc=0):
      # x is "closed" in the definition of inc
      nonlocal x
      x += moreinc
      return y + x
   return inc

f = makeInc(23)
fclose = f.__closure__  # a tuple of 'cells'
fcell = fclose[0]

print(dir(fcell))
# ['__class__', '__delattr__', '__dir__', '__doc__', '__eq__',
# '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__',
# '__init__', '__init_subclass__', '__le__', '__lt__', '__ne__',
# '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__',
# '__sizeof__', '__str__', '__subclasshook__', 'cell_contents']
# Note: no mutation method

print('cell content = ', fcell.cell_contents)
# cell content = 23

fcell.cell_contents = 32
### results in
Traceback (most recent call last):
   File "F:\Python\mypy\tem.py", line 14, in <module>
     fcell.cell_contents = 32
AttributeError: attribute 'cell_contents' of 'cell' objects is not writable
# unless one does so from within the closure body with 'nonlocal' 
declaration.  I presume there is a special byte code for this.


-- 
Terry Jan Reedy




More information about the Python-list mailing list