I have a template script as follows.
from shared import C
def do(ins):
ins.x()
def main():
try:
ins = C(1,'a')
do(ins)
except:
ins.handle()
else:
ins.finalize()
if __name__ == '__main__':
main()
How to move try-except-else in decorator to avoid code duplication in every script based on template?
I create a decorator dec
like below in shared.py
which also contains class C
from functools import wraps
def dec(ins):
def a(f):
@wraps(f)
def b(*a, **k):
try:
f(*a, **k)
except:
ins.handle()
else:
ins.finalize()
return b
return a
Failed attempt 1: Create instance in main and pass to main2
from shared import C, dec
def do(ins):
ins.x()
@dec(ins)
def main():
ins = C(1, 'a')
do(ins)
if __name__ == '__main__':
main()
Failed attempt 2: Set ins within decorator
from shared import C, dec
def do(ins):
ins.x()
@ins = dec(C(1, 'a'))
def main():
do(ins)
if __name__ == '__main__':
main()
Failed attempt 3: Create instance in main idiom
from shared import C, dec
def do(ins):
ins.x()
@dec(ins)
def main():
do(ins)
if __name__ == '__main__':
ins = C(1, 'a')
Successful attempt: Global variable
from shared import C, dec
ins = C(1, 'a')
def do(ins):
ins.x()
@dec(ins)
def main():
do(ins)
if __name__ == '__main__':
main()
How to avoid creating global?
EDIT:
You could modify your class do do the handling, which removed the need of a decorator.
class C:
def execute(self, func):
try:
func(self)
except:
self.handle()
else:
self.finalize()
def main():
ins = C(1, 'a')
C.execute(do)
You can achieve this by wrapping the do functions which has all necessary infos.
def do_wrapper(do_func):
@wraps(do_func)
def wrapped_do(ins):
try:
do_func(ins)
except:
ins.handle()
else:
ins.finalize()
return wrapped_do
@do_wrapper
def do(ins):
ins.x()
def main():
ins = C(1, 'a')
do(ins)
Note you can also wrap functions 'on-the-fly' which previously were not wrapped.
def main2():
do_wrapper(do)(ins) # here the do function is wrapped on the fly