Note, your question is basically asking for a primer on dependency injection. You would probably do well to read up on it. It's language-agnostic - it applies as nicely to Java as it does to Python.
There are several different approaches you can take for this; the best choice depends on your needs and what the functions involved do (which is why I was asking all the questions in the comment).
The simplest form of what you're looking for is to just have one function invoke the other. (COLDSPEED made reference to this.):
def func1(input):
# do some magic to my_list with input
return my_list
def func2(input):
func1_list = func1(input)
# do some magic to make func2's my_list
return my_list
In that case, func1 and func2 are both able to be called. The importing code doesn't have to worry about calling func1 before func2 - that's taken care of by func2.
Before I get into your other choices, you mentioned that both functions output information. It's a good practice to separate your calculations from your output of them. So, DON'T do this:
def func1(input):
# do some magic to my_list with input
print("func1: Stuff from my list...")
return my_list
def func2(input):
func1_list = func1(input)
print("func2: Stuff from my list...")
# do some magic to make func2's my_list
return my_list
Because then calling func2
would print out the "func1" line and the "func2" line. Instead, separate the logic from the output. It may seem more complicated, but it gives you more building blocks to play with:
def func1(input):
# do some magic to my_list with input
return my_list
def func2(input):
func1_list = func1(input)
# do some magic to make func2's my_list
return my_list
def output_func1(input):
func1_list = func1(input)
print("func1_list stuff")
def output_func2(input):
func2_list = func2(input)
print("func2_list stuff")
Now you have a lot of reusable functions that don't generate a lot of noise.
This is a good step, and you can use this easily. What happens if func1
takes an hour to run? You don't want to run it again if it's already been run. Then you want to use module variables to save state. Something like this:
func1_results = None
def func1(input):
# do some magic to my_list with input
func1_results = my_list
return my_list
def func2(input):
if not func1_results:
func1(input) # this will only run if func1 hasn't been called yet
# do some magic to make func2's my_list
return my_list # you could similarly make a construct to save these results
Now you get code calling its dependencies only if it needs to. We're getting better. But we're passing input into func2, and we only care about it in func1. You could make a module variable input
that func1 refers to, and your importing code could set it before calling any of the funcs:
input = None
def func1():
# do some magic to my_list with module variable input
And invoke it as:
import my_funcs
my_funcs.input = "Happy happy input!"
my_funcs.func1() # or just my_funcs.func2(), etc.
This could be nice, but it's dangerous - what if the importing code doesn't set input
? The solution to that is what Fabien mentioned about having a class:
class FuncRunner(object):
def __init__(self, input):
self.input = input
self.func1_results = None
def func1(self):
# do some magic to local my_list with input
self.func1_results = my_list
return my_list
def func2(self):
if not self.func1_results:
self.func1()
# do some magic to make func2's my_list
# maybe save the result as self.func2_results ?
return my_list
This would be invoked as:
from my_funcs import FuncRunner
runner = FuncRunner("Happy happy input!")
foo = runner.func1() # or foo = runner.func2(), as per your needs
This does the nice thing of not letting you run functions without constructing the object, and the way the __init__
is structured, you can't create the object without passing input
. The results found by func1
are stored within the object, so they're always associated together. In your case, this is likely the cleanest way to do what you want.