Reputation: 1250
Is there a way to trigger a function automatically if any of a list of functions is called in python?
Like say function a is attached to a list of functions [b, c, d, e] and if either of [b, c, d, e] is called (for example say b()) then a() is called automatically before it?
I want to use function a to set up some values before b is called so that b can use it.
Like for example:
# function b is some inbuilt, library function
attach(a, b) #attach function b to function a
b()
# If function b is called first function a gets called, it changes up some
# global variables for the use of function b, then function b gets executed
I have some global variables and some class methods, The global variables are somethings like CLASSIFIER(e.g. LogisticRegression or XGBClassifier), CLASSIFIER_TYPE(e.g. 'linear' or Tree) which I need to change everytime I call fit and predict methods on their respective pipelines (e.g. pipeline_linear or pipeline_tree).fit/predict. This is because I have written code like:
CLASSIFIER = LogisticRegression
CLASSIFIER_TYPE = 'linear'
pipeline_linear = make_pipeline(preprocessing_pipe, CLASSIFIER())
pipeline_linear.fit(X, y)
CLASSIFIER = XGBClassifier
CLASSIFIER_TYPE = 'tree'
pipeline_tree = make_pipeline(preprocessing_pipe, CLASSIFIER())
pipeline_tree.fit(X, y)
linear_preds = pipeline_linear.predict(X) # This statement throws an error
# because CLASSIFIER and CLASSIFIER_TYPE are not changed
# preprocessing_pipe uses CLASSIFIER_TYPE internally to take care of
# handling both types of classifiers differently.
So based on the pipeline I am using, the global variables need to be modified accordingly in order for the fit and predict methods to work on the pipelines(pipeline_linear and pipeline_tree).
Any other good approach to take care of these situations will be really helpful!
Upvotes: 0
Views: 1036
Reputation: 59731
I think you can still use something like a decorator/wrapper. See if something like this could work for you:
MY_GLOBAL = 123
def wrap_with_global_value(func, global_val):
def wrap(*args, **kwargs):
global MY_GLOBAL
prev_global_val = MY_GLOBAL
MY_GLOBAL = global_val
result = func(*args, **kwargs)
MY_GLOBAL = prev_global_val
return result
return wrap
class MyClass(object):
def my_func(self):
global MY_GLOBAL
print('from my_func: MY_GLOBAL is {}.'.format(MY_GLOBAL))
my_obj = MyClass()
my_obj.my_func = wrap_with_global_value(my_obj.my_func, 456)
print('Before calling my_func: MY_GLOBAL is {}.'.format(MY_GLOBAL))
my_obj.my_func()
print('After calling my_func: MY_GLOBAL is {}.'.format(MY_GLOBAL))
Output:
Before calling my_func: MY_GLOBAL is 123.
from my_func: MY_GLOBAL is 456.
After calling my_func: MY_GLOBAL is 123.
You can add functools.wraps
if that is important for you.
Upvotes: 2
Reputation: 286
Surely it would be easier to just call the function at the top of each other function?
def setup():
# Set some variables
pass
def target1():
setup()
pass
def target2():
setup()
pass
Upvotes: 0
Reputation: 357
Use a wrapper.
If your function is my_function
and your list is list_of_functions
:
def func_wrapper(query):
for additional_function in list_of_functions:
# Do whatever you need to do with your list of functions
additional_function()
my_function(query)
Upvotes: 2