Choosing one of several methods on object instantiation


February 2019


10 time


I have a python class, let's call it MyClass, with several bound methods. I need the behaviour of one of these methods, call it .dynamic_method(), to be drastically different depending on the value of a parameter set during object creation. There will be a handful of variations of dynamic_method which will share very little code between them, so it makes sense to define them as separate functions/methods rather than as a single large method with many options and conditionals. I do not need to be able to change the behaviour of this method after creating the object, everything can be set during __init__().

For reference, MyClass manages data sets, and .dynamic_method deals with some IO aspects of this data which change depending on dataset and context.

This is not technically difficult to achieve, but none of the methods I've come up with feel completely correct:

  1. Define the method variations as functions separately, and attach one of them as a bound method during __init__() using one of the methods described here: Adding a Method to an Existing Object Instance. This seems like the most natural choice to me, but many of the answers in that thread strongly discourages the use of this pattern.
  2. Define all possible methods in the class definition as .dynamic_method_a, .dynamic_method_b etc, and set an option/alias so that MyClass.dynamic_method() calls the correct one. This will result in a very long class definition, and lots of unused methods for each object.
  3. Store the methods as separate functions, and have .dynamic_method() simply calls the correct function with self as the first argument. This feels like a wilful misuse of the concept of methods, and will break linting.
  4. Use a factory pattern or object generator function. I'd rather avoid this, as it will add by far the most complexity to the code base.

What would be considered the most "Pythonic" way to achieve this behaviour? One of the above methods, or is there an obvious alternative I've missed?

0 answers