0

Within the scope of a function, I want to define and execute a closure which captures variables which exist only within the scope of the "outer" function.

I have found through experimentation that if assigning to a captured variable, it doesn't work by default: the line i+=1 looks for a local i when assigning. However the usual solution — which would work without the wrapping "outer" function — doesn't work here:

def outer(): i = 1 n = 10 def inner(): global i, n i += 1 return i == n while not inner(): pass print("done") outer() # NameError: name 'i' is not defined # (on the line `i += 1`) 

I know I could pass the captured variables as arguments to inner instead, but for my real case inner will be passed as data and executed elsewhere (within outer), so I'd ideally not want to have to partial it: closures seem a natural fit.

Is there a clean, clear way I can make this work in Python? Bonus points if there is a way I can make this work without typing global, which always makes me feel uneasy.

1
  • 1
    global doesn't work here because the scope you are attempting to access is not global. It's nonlocal. That being said, partial or lambda is probably a better solution. But it's hard to say without knowing the specific problem. Commented Dec 7, 2020 at 10:54

1 Answer 1

1

Use nonlocal instead of global.

def outer(): i = 1 n = 10 def inner(): nonlocal i i += 1 return i == n while not inner(): pass print("done") outer() # done 

Thanks to Axe319 in the comments.

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

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.