1

On the few occasions I have had to do this I have used the global keyword. Currently I am cleaning up some code that's not mine which is basically 200 hundred lines after a While statement with no closures. I'd like to separate everything functionally into smaller bits but the problem is that there are a lot of references to the same variables all over those 200 lines. Is there a way to give a nested function access to All Parent Variables without declaring them explicitly?

The original really long while statement:

While True:  
    var1, var2, var3, var4 = x, [], {}, y
    #does something with var2, var3 and var4
    #does something with var1 and var3
    #does something with var4 and var1
    #etc. 

to ---> Edit: Would this be an incorrect solution, if so why?

class My:
    pass
def foo(): 
   #does something with My.var2, My.var3 and My.var4
def bar(): 
   #does something with My.var1 and My.var3
def tar(): 
    does something with My.var4 and My.var1
While True:
    My.var1, My.var2, My.var3, My.var4 = x, [], {}, y
    #There are a lot of variables to keep track off and declaring each one
    # as global will take a lot of extra declarations
    foo() 
    bar()
    tar() 
2
  • 1
    Defining your functions each time through the loop is going to add a lot of overhead. Define the functions outside the loop, and pass the necessary data as parameters, returning appropriate values. Commented Jul 11, 2014 at 14:41
  • Related: stackoverflow.com/a/24682708/3001761 Commented Jul 11, 2014 at 14:51

3 Answers 3

2

Another way to keep track of similar variables is to put them in a class. For example:

class MyClass(object):
    def __init__(self, v1, v2, v3, v4):
        self.var1 = v1
        self.var2 = v2
        self.var3 = v3
        self.var4 = v4

    def run(self):
        while True:
            self.foo()
            self.bar()
            self.tar()

    def foo(self):
        """does something with var2, var3 and var4"""
        return self.var2, self.var3, self.var4

    def bar(self):
        """does something with var1 and var3"""
        return self.var1, self.var3

    def tar(self):
        """does something with var4 and var1"""
        return self.var4, self.var1


if __name__ == "__main__":
    mc = MyClass('x', [], {}, 'y')
    mc.run()
Sign up to request clarification or add additional context in comments.

Comments

0

Change your functions to use parameters and also get the functions out of that while loop.

For example:

def foo(var2, var3, var4)
    return var2 + var3 + var4

def bar(var1, var3)
    return var1 * var3

...
While True:
    var5 = foo(var2,var3,var4)

    var1 = bar(var1,var3) 

etc.

5 Comments

Is there an actual effective way to get locals() out of one scope passed down to another?
Can you please expand on what you mean by that?
Using a class "packages" all of the variables you care about as one object. If you pass that class instance to another object you will have access to its attributes. Similarly you could do the same with a dictionary and pass that around, effectively keeping all your variables together. var_dict = {'var1': x, 'var2': [], 'var3': {}, 'var4': 'y'}
Would it be possible to make it a local reference though? so instead of having to call MyClass.var4 or MyDict['var4'] I could just call var4 without explicitly defining it ?
Is that so you do not need to make a bunch of code changes? You could pass it in with the dictionary, and then create a variable with the value you want... var4 = MyDict['var4']. Then you could use var4 as normal. If you update the value, though, you're going to need to update it in the dictionary in order to pass those changes to another scope.
0

I have a function which calls scipy.optimize.fmin_l_bfgs_b() That function takes another function which is called repeatedly. I have several versions of this same function, using different optimization ways that the user can choose.

To keep them all together, I do what you are talking about, but I make sure to do the loop outside of the actual instantiation method. So, it would look like this:

`def MethodOne(var1, var2): def InnerFn1(...): ... def InnerFn2(...): ....

for i in range(0, var1):
    CallFunctionWhichCallsAnFnAbove(var2, InnerFn1, InnerFn2, i)

`

That allows me to encapsulate all of the related components together, without any real penalty. var1 and var2 are accessible for reading within both inner functions even if you don't add them as parameter in your call, due to standard python scoping.

Comments

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.