Reputation: 902
How i can to inject code in class method.i have to use this many method (app_one app_two...). i think code is not beauty and look like to duplicate in multiline. i want to know how i can to refactor this code ?
class Main:
def step_one(self):
print("STEP 1")
def step_tree(self):
print("STEP 3")
def app_one(self):
self.step_one()
/// do_something
self.step_two()
def app_two(self):
self.step_one()
/// do_something
self.step_two()
def app_three(self):
self.step_one()
/// do_something
self.step_two()
thank for expert.
Upvotes: 3
Views: 906
Reputation: 23
something like this?
class Main:
def step_one(self):
print("STEP 1")
def step_tree(self):
print("STEP 3")
def app_one_function(self):
# do_something_app_one_unique
def app_two_function(self):
# do_something_app_two_unique
def app_three_function(self):
# do_something_app_three_unique
def run_app(self, function):
self.step_one()
function()
self.step_two()
Or you could use decorator like this
def decorator(function):
def decorated(cls):
cls.step_one()
function(cls)
cls.step_two()
return decorated
class Main:
def step_one(self):
print("STEP 1")
def step_tree(self):
print("STEP 3")
@decorator
def app_one(self):
# do_something_app_one_unique
@decorator
def app_two(self):
# do_something_app_two_unique
@decorator
def app_three(self):
# do_something_app_three_unique
obj = Main()
obj.app_one()
obj.app_two()
Upvotes: 1
Reputation: 70287
We can define a decorator that takes an ordinary instance method and turns it into one with your desired prologue and epilogue. Here's what our decorator will look like
def wrapped_app(fn):
def wrapped_fn(self, *args, **kwargs):
self.step_one()
fn(self, *args, **kwargs)
self.step_three()
return wrapped_fn
So given a function fn
, wrapped_app
returns a new function (which we locally call wrapped_fn
) which does self.step_one()
, then fn
, then self.step_three()
. We can use it with decorator syntax inside the class now
class Main:
def step_one(self):
print("STEP 1")
def step_three(self):
print("STEP 3")
@wrapped_app
def app_one(self):
print("App one")
@wrapped_app
def app_two(self):
print("App two")
@wrapped_app
def app_three(self):
print("App three")
We can check that it works as follows
>>> main = Main()
>>> main.app_one()
STEP 1
App one
STEP 3
We can also go one step further. Your current app_one
et al don't return anything, but it is possible that we may want such functions to be capable of returning. A slight modification to wrapped_fn
will take care of that eventuality. Similarly, we may also want step_three
to be guaranteed to run, even in the case that our app function fails or raises an exception. We can use try ... finally
to do so.
def wrapped_app(fn):
def wrapped_fn(self, *args, **kwargs):
self.step_one()
try:
result = fn(self, *args, **kwargs)
finally:
self.step_three()
return result
return wrapped_fn
Upvotes: 4
Reputation: 12068
One approach is to use decorators:
from functools import wraps
def call_step_one_step_two(func):
@wraps(func)
def wrapper(self, *args, **kwargs):
self.step_one()
func(self, *args, **kwargs)
self.step_two()
return wrapper
class Main:
def step_one(self):
print("STEP 1")
def step_two(self):
print("STEP 3")
@call_step_one_step_two
def app_one(self):
// do something
@call_step_one_step_two
def app_two(self):
// do something
@call_step_one_step_two
def app_three(self):
// do something
All methods wrapped in this decorator will always call step_one
before the method, and step_two
after the method. This does not support returning values though. Hope this is enough.
Upvotes: 2