thkang
thkang

Reputation: 11543

changing values inside a local space by a function in that local space

here's a sample code:

def foo():
    def bar():
        foobar = 'foobaz'

    foobar = 'foobar'
    print foobar
    bar()
    print foobar

foo()

I want to change variable foobar inside foo by function bar. The code above will not work, since foobar inside bar is in separate namespace with foobar in foo. A simple workaround would be making a global foobar and have both foo and bar can access it, but I hope there would be simpler workarounds.

Upvotes: 0

Views: 85

Answers (5)

martineau
martineau

Reputation: 123501

Even though functions are already first class objects in Python, you can create your own "functor" or function object something like this:

class Foo(object):
    def bar(self):
        self.foobar = 'foobaz'

    def __call__(self):
        self.foobar = 'foobar'
        print self.foobar
        self.bar()
        print self.foobar

foo = Foo()
foo()

Upvotes: 0

Ashwini Chaudhary
Ashwini Chaudhary

Reputation: 251096

On python 3.x you can use nonlocal and for python 2.x try using function attributes:

def foo():
    def bar():
        foo.foobar = 'foobaz'  #change the function attribute

    foo.foobar = 'foobar'     #declare as function attribute
    print foo.foobar
    bar()
    print foo.foobar
foo() 

output:

foobar
foobaz

Upvotes: 2

Raunak Agarwal
Raunak Agarwal

Reputation: 7238

def foo():
    def bar():
        foobar = 'foobaz'
        return foobar

    foobar = 'foobar'
    print foobar
    foobar = bar()
    print foobar

foo()

Upvotes: 0

Eric
Eric

Reputation: 97641

Not possible in python 2.7. In python 3:

def foo():
    def bar():
        nonlocal foobar
        foobar = 'foobaz'

    foobar = 'foobar'
    print foobar
    bar()
    print foobar

foo()

In 2.x, you can do:

def foo():
    foobar = []
    def bar():
        foobar[0] = 'foobaz'

    foobar[0] = 'foobar'
    print foobar[0]
    bar()
    print foobar[0]

foo()

Upvotes: 1

Gareth Latty
Gareth Latty

Reputation: 89077

You are looking for the nonlocal keyword, which exists in 3.x.

def f():
    x = None
    def g():
        nonlocal x
        x = 1

If you are stuck in 2.x, you can do it by having a list or similar mutable data container and accessing that as a work around.

def f():
    x = [None]
    def g():
        x[0] = 1

This works as variables do fall into scope, but won't leak out of scope. With mutable objects, we can change them inside the scope, and those changes propagate out.

Upvotes: 2

Related Questions