DESC icon indicating copy to clipboard operation
DESC copied to clipboard

Simplify `Objective` class args and docstrings

Open f0uriest opened this issue 1 year ago • 3 comments

We have an ever growing number of objectives, with pretty much all of the init methods being something like this

def __init__(self, thing, 
target, 
bounds, 
weight, 
normalize, 
... (other args generic to all objectives), 
arg1_specific_to_this_objective, 
arg2_specific_to_this_objective
):

And each of the args is documented separately in each class. This means that if we want to add a new property generic to all objectives (like we did with loss_function, normalize, deriv_mode, etc) we have to add it to ALL of the init methods and docstrings

A cleaner method that requires less duplication could be something like

def __init__(self, 
thing, 
arg1_specific_to_this_objective, 
arg2_specific_to_this_objective, 
**kwargs_generic_to_all_objectives
):

Doing this in combination with something like https://github.com/AntoineD/docstring-inheritance would allow us to reduce the amount of redundant docstrings in the code while still having all the args documented to the user in an IDE or docs page. We could also get fancy and override the subclass __signature__ attribute to include the extra args from the parent class.

f0uriest avatar Feb 15 '24 20:02 f0uriest

Something like this might be easier:

import inspect

class Base():
    """Base docstring"""
    
    def __init__(self, *, base_arg1="auto", base_arg2=None):
        self.base_arg1 = base_arg1
        self.base_arg2 = base_arg2
        
    # https://docs.python.org/3/reference/datamodel.html#object.__init_subclass__
    def __init_subclass__(cls, /, **kwargs):
        super().__init_subclass__(**kwargs)
        cls.__doc__ = cls.__doc__ + Base.__doc__
        sig = inspect.signature(cls)
        sig = sig.replace(parameters=tuple(sig.parameters.values())[:-1] + tuple(inspect.signature(Base).parameters.values()))
        cls.__signature__ = sig
    
    
class Derived(Base):
    """Derived docstring"""
    
    def __init__(self, arg1, arg2, **kwargs):
        self.arg1 = arg1
        self.arg2 = arg2
        super().__init__(**kwargs)

This seems to correctly set the docstring and signature for the derived class, at least in jupyter

f0uriest avatar Mar 07 '24 01:03 f0uriest

keyword-only args in addition to above, try for just Objectives @f0uriest

dpanici avatar Jun 25 '24 19:06 dpanici

Would we like to inherit the docstrings for only documentation website purposes or do we also want to see the documentation when we hover on the class name in VSCode? I would prefer the latter but it is a bit harder I guess.

YigitElma avatar Sep 21 '24 15:09 YigitElma