2

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.

6
  • Maybe it is possible but I would never use a variablename twice in the same file/class. I'm not sure but it might be against the pip rules. Commented Nov 20, 2014 at 18:06
  • 1
    Why do you want to implement JavaScript closures in Python, why not Python functions? Commented Nov 20, 2014 at 18:11
  • Man, that title. Is writing a proper title for a question a lost art now? Commented Nov 20, 2014 at 18:11
  • I am writing a translator and JavaScript has a bit different closures. Commented Nov 20, 2014 at 18:11
  • 1
    Basically inside one function you can have var be a local variable or a global variable, but you can't have it mean both things in the same function. Commented Nov 20, 2014 at 18:51

3 Answers 3

2

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.

Sign up to request clarification or add additional context in comments.

9 Comments

It has to have the same name, this is the point. And global will not work for nested functions.
@PiotrDabkowski: If you're trying to make your translator work without variable renaming, you're making things a lot harder for yourself than you need to. What happens when you need to translate a variable named $foo?
Its all stored inside var which represents scope :). so $foo=4 will translate to var.put('$foo', Js(4))
@PiotrDabkowski: You can just number the vars according to the nesting level and have your translator use the right name for each access.
@user2357112 I thought about it but it would be much harder to implement and the resulting code would be impossible to read. var=var is a better option than using different names for scope variable.
|
1

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}).

Comments

0

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.

3 Comments

I am using python 2.7 nonlocal is not implemented here :(
sorry, this also will not work in python3, because there is only global var exists and no others.
I fix my answer. It will work for closures of global variables.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.