If you're writing a conventional Python program, the most natural way of putting multiple function together into a single function-bundle to access them as bundle_name.function_name()
is to locate them is a separate file and import it as a module every time you need them.
Things are getting more complicated as you start using IPython notebook, because you are basically working in a single IPython session and there's no single clear solution for the problem of splitting the logic of a complex application into several modules (on the function level, at least). These are few that came to my mind:
- Defining classes and using
@staticmethod
for each function or using a class decorator for it:
.
import inspect
def act_as_module(cls):
for name, func in inspect.getmembers(cls, predicate=inspect.ismethod):
setattr(cls, name, staticmethod(cls.__dict__[name]))
return cls
@act_as_module
class NiceClass:
def func1(a, b):
return a+b
- Writing to the file and re-importing every time
cell1:
%%writefile test_module_tmp.py
def func1(a, b):
return a+b+3
cell2:
%load_ext autoreload
%autoreload 1
%aimport test_module_tmp
cell3:
test_module_tmp.func1(10, 20)
- the good part of is that you can re-use those util-functions from other notebooks + you're not 'reinventing' custom decorator that could be hard to comprehend by other people.
The main drawback is that you utilize multiple cells that needs to be called in a specific order to work properly and every time you restart your session, you need those 're-load definitions' to be re-executed and etc. And you also can't write 'test()' functions on the bottom of those cells to that they'd be executed and their output would be redirected into the cells output right under the cell every time you change and re-run it (so that you'll see if something got broken right after you press Ctr+Enter inside of this module-cell, like def func1(): ..; def test_func1():..; test_func1()
- and run it in a single batch).
I wonder if there's any solid out-of-box solution for this problem?