On Tue, Sep 27, 2016 at 3:19 PM, Terry Reedy <tjre...@udel.edu> wrote: > On 9/27/2016 11:01 AM, Chris Angelico wrote: >> >> On Wed, Sep 28, 2016 at 12:01 AM, Peng Yu <pengyu...@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.
You could, however, put a mutable object in the cell variable and then modify it from without. E.g.: def makeInc(x): x = [x] def inc(y, moreinc=0): x[0] += moreinc return y + x[0] return inc f = makeInc(23) fcell = f.__closure__[0] fcell.cell_contents # [23] fcell.cell_contents[0] = 42 f(0) # 42 -- https://mail.python.org/mailman/listinfo/python-list