Reputation: 6835
I have a large function in my script that contains the bulk of the logic of my program.
At one point, it used to span ~100 lines which I then tried to refactor into multiple smaller functions. However, I had many local variables that were eventually being modified in the smaller functions, and I needed some way to keep track of them in the scope of the larger function.
For instance, it looked like
def large_func():
x = 5
... 100 lines ...
to
def large_func():
x = 6
small_func_that_will_increment_x()
small_func()
....
What is a pythonic way to handle this?
The two approaches I can think of are:
1) global variables --- will probably get messy as I have many variables 2) using a dict to keep track of them like
tracker = {
'field1' : 5
'field2' : 4
}
and make modifications on the dict instead.
Is there a different way to do this that I might have overlooked?
Upvotes: 3
Views: 2717
Reputation: 3702
Object composition. Create small objects that hold state, and then feed them as initializers an object that manages them. See Global State and Singletons
"Build the door knob, which you use to build the door, which you use to construct the house. Not the other way around"
Upvotes: 0
Reputation: 7146
Another tip - make use of Python's ability to return multiple values. If you have a function that modifies two variables, do something like this:
def modifies_two_vars(a, b, c, d):
return a+b, c+d
x, y = modifies_two_vars(x, y, z, w)
Upvotes: 3
Reputation: 19347
One alternative could be:
def small_func_that_will_return_new_x(old_x):
return old_x + 1
def large_func():
x = small_func_that_will_return_new_x(6)
instead of:
def large_func():
x = 6
small_func_that_will_increment_x()
Upvotes: 0
Reputation: 365667
Without more information, it's hard to know whether this is appropriate or not, but…
An object is a namespace. In particular, you can turn each of those local variables into attributes on an object. For example:
class LargeThing(object):
def __init__(self):
self.x = 6
def large_func(self):
self.small_func_that_will_increment_x()
self.small_func()
# ...
def small_func_that_will_increment_x(self):
self.x += 1
Whether the self.x = 6
belongs in __init__
or at the start of large_func
, or whether this is even a good idea, depends on what all those variables actually mean, and how they fit together.
Upvotes: 6
Reputation: 97571
Closures will work here:
def large_func()
x = 6
def func_that_uses_x():
print x
def func_that_modifies_x():
nonlocal x # python3 only
x += 1
func_that_uses_x()
func_that_modifies_x()
Upvotes: 3