user3467349
user3467349

Reputation: 3191

Python: Access all Parent Variables in Nested Function

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() 

Upvotes: 1

Views: 296

Answers (3)

Nick
Nick

Reputation: 324

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()

Upvotes: 2

user632657
user632657

Reputation: 493

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.

Upvotes: 0

Scott
Scott

Reputation: 15

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.

Upvotes: 0

Related Questions