1

Is it possible to write a function in python, which takes an argument a and prints the result of h+a where h is a local variable. Then it should return itself, with h increased by one.

Moe
  • 1,021
  • 1
  • 9
  • 16
  • 1
    But why? You should change the title to emphasize learning about closures -- otherwise you may get a lot of people telling you that `simulating static variables is a waste of time -- python already has them!` Also, they're not called static variables in python. – Matt Fenwick Nov 17 '11 at 22:32
  • i was just curious if it's possible because i wasn't able to create my own solution. and i wasn't sure how to title the question. – Moe Nov 17 '11 at 22:48

2 Answers2

5

In python 3, you can do this:

>>> def f(a):
...     h = 1
...     def inner():
...             nonlocal h
...             print(a+h)
...             h += 1
...             return inner
...     return inner
... 
>>> g = f(3)  
>>> g = g()
4
>>> g = g()
5 
>>> g = g()
6
>>> g()()()
7 
8
9
<function inner at 0xb71bcd6c>

Previous versions required faking it:

>>> def f(a):
...     h = [1]
...     def inner():
...             print a + h[0]
...             h[0] += 1
...             return inner
...     return inner
... 
>>> f(3)()()()
4  
5
6
<function inner at 0x10041f050>
>>> 

(ETA: I guess I misinterpreted part of the question, since it seems you want the function returned by f (and that returns itself) to take the argument, but that's a trivial change.)

ben w
  • 2,490
  • 14
  • 19
  • 2
    basically, before python3, if you tried to *assign* to h in inner(), "h" is considered local to inner(). So you have two options: (a) assign then use. Then h in inner() shadows the h in f(), and it isn't preserved across calls, and that's not what you want. (b) use then assign. But since it's considered local to inner, you can't use it before assigning it---it's not bound yet. With h = [1], all you're doing in inner is using it---you refer to it, but you never assign to *h itself*. you just assign to h[0]. – ben w Nov 18 '11 at 02:52
2

Yes, you can

def f(a):
    def inner(h, a):
        print h+a
        return lambda (x): inner(h+1, x)
    return inner(1, a)

example

g = f(0) # +1
g = g(0) # +2
g = g(0) # +3

f(0) # +1
g(0) # +4
g(0) # +4

prints

1
2
3
1
4
4

Q.E.D.

sehe
  • 374,641
  • 47
  • 450
  • 633
  • This isn't incrementing a local variable. You're really only simulating what the poster wants. – ben w Nov 17 '11 at 23:08