0

I am having a lot of different functions that are going to be operated on instances of a specific class, DSM. I would like to have them working both as instance functions to the class, as well as separate functions on a module level. The functions are currently stored in two different modules, similarity.py and compositions.py, while the class is stored in model.py.

As such, I could import the functions from each module and apply the functions on the class in a traditional manner, similarity.cos(dsm_instance, arg1, arg2), which is what I want. What I want as well is to have all functions in each module automatically added to the class instance, so I could call dsm_instance.cos(arg1, arg2).

Because the class instances take a lot of time to create I am caching each instance as soon as they are created. Because of this I would prefer if the functions from each module were added to the class instance in runtime. This is to be able to fix any bugs and add new functionality to each class instance without the need to recreate the instance itself.

To summarize: How do I automatically add all functions from specific modules in such a way that the functions are added in runtime and not when the instance first is created?

Jimmy C
  • 9,270
  • 11
  • 44
  • 64
  • Add them to the class instead? – univerio Jun 25 '14 at 18:42
  • Use multiple inheritance, mix-in class. – Keith Jun 25 '14 at 18:48
  • Isn't it better to use unit tests to make sure everything works properly in advance? – jcfollower Jun 25 '14 at 18:57
  • @univerio: If I do, new functions and fixes of existing functions aren't implemented on the cached class. The amount of functions also makes it preferable to have them separated. – Jimmy C Jun 25 '14 at 19:04
  • @jcfollower: Already using unit testing, but bugs still happen to appear every now and then. Also, that wouldn't solve adding new functions to the class after initialized. – Jimmy C Jun 25 '14 at 19:06
  • @JimmyC When you say "new functions and fixes of existing functions", do you mean that you'll have the interpreter open while you modify your files and have python *reload the modules on the fly*? – univerio Jun 25 '14 at 19:21
  • @univerio: I mean that I often add new functions to the class because of testing new experiments, etc. Since the class is created by analyzing a few gigs of data, I don't want to recreate the class. While the easiest thing to implement is to keep the functions in a separate module, it is more handy to have them as instance methods when using a Python REPL as IPython. Python won't need to reload them on the fly, only when I load the cached class. – Jimmy C Jun 25 '14 at 19:35
  • @JimmyC Then in your reload function, just modify the class with the new functions and all your instances will use the new version. – univerio Jun 25 '14 at 20:00

1 Answers1

1

This feels a bit hackish, but the following will work. I'm using scikit-bio as an example just because it was readily available. If you define __all__, or some other variable in your module that contains the names of interest, you can import it and dynamically update on the subsequent object.

Hope this helps!

>>> class foo(object):
...   def update_namespace(self):
...     import skbio
...     reload(skbio)
...     from skbio import __all__ as namespace_to_update
...     for func in namespace_to_update:
...         setattr(self, func, getattr(skbio, func))
...
>>> bar = foo()
>>> dir(bar)
['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'update_namespace']
>>> bar.update_namespace()
>>> dir(bar)
['Alignment', 'BiologicalSequence', 'DNA', 'DNASequence', 'DistanceMatrix', 'FastaIterator', 'FastqIterator', 'NucleotideSequence', 'Protein', 'ProteinSequence', 'RNA', 'RNASequence', 'SequenceCollection', 'SequenceIterator', 'TreeNode', '__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'local_pairwise_align_ssw', 'nj', 'parse_fasta', 'parse_fastq', 'parse_qual', 'update_namespace']
daniel
  • 2,568
  • 24
  • 32
  • This works splendidly to add the functions to the class, but unfortunately it doesn't seem to be added as instance methods. That is, when calling the `foo.bar(self)`, `self` isn't considered to be the class itself, and I have to add it manually. Do you have a solution for this? – Jimmy C Jun 26 '14 at 08:32
  • Not off the top of my head right now, will think on it. Very curious to see what you come up with. – daniel Jun 26 '14 at 21:12
  • @JimmyC, have you seen [this](http://stackoverflow.com/questions/972/adding-a-method-to-an-existing-object) post? [This](http://www.ianlewis.org/en/dynamically-adding-method-classes-or-class-instanc) one as well, the latter I think has a solution for you. – daniel Jun 27 '14 at 18:42