Piotr Dabkowski
Piotr Dabkowski

Reputation: 5939

How can I implement Javascript closures in Python?

I am trying to implement Javascript closures in Python 2.7.

Consider the following code:

var = {'upper_scope':None}

def f1():
    print var

def f2():
    var = {'upper_scope': var}

The first function works fine. The second one fails on its first line:

UnboundLocalError: local variable 'var' referenced before assignment. 

I would like to read the value of var from the upper scope and place it inside a local dictionary named var.

Upvotes: 2

Views: 130

Answers (3)

Piotr Dabkowski
Piotr Dabkowski

Reputation: 5939

This is probably the only way of doing that. I used this method in my JavaScript to Python converter and it does it's job.

var = {'upper_scope':None}
def first(var=var):
    var = {'upper_scope': var}
    def second(var=var):
        var = {'upper_scope': var } 
        def third(var=var):
             var = ...

Now each function 'remembers' its upper scope - its stored a as its default argument. Also note that the function automatically creates local scope when called (var = {'upper_scope': var}).

Upvotes: 1

kammala
kammala

Reputation: 427

There is nonlocal statement in python3 syntax which was invented exactly for what you asked: for access to names in outer scope.

For access global varible in nest of functions you can do something like this(works in both python2 and python3):

var = {'upper_scope':None}
def first():
    global var
    var = {'upper_scope': var}
    def second():
        global var
        var = {'upper_scope': var } 
        def third():
            global var
            var = ...

In all of these functions will exist only one example of variable var — the global one. So every changes in inner scope will be available on higher level and vice versa.

Upvotes: 0

sysconfig
sysconfig

Reputation: 1407

It doesn't work in f2(), because you are locally overwriting the global definition of var. If you rename var in f2(), it will work:

def f2():
   other_var = {'upper_scope': var}

Alternatively, you could define it as global, but then the change of var's value would be applied to the global variable, too, like so:

def f2():
   global var
   var = {'upper_scope': var}

That being said, it's always a better approach to pass variables as parameters to functions, unless you really need it in several places and/or need to change its value.

Upvotes: 2

Related Questions