Skip to content

A patching pattern

When some functionality is not quite what you expected from a library, or you wanted to enhance it with some additonal features, a useful pattern is to patch them dynamically.

Here are a few examples

Example 1: add a lookup method to DataFrame

As a cute utility function, we can add a lookup method to a DataFrame, which returns the column names that contains the queried string

import polars as pl

def lookup(self, name:str):
    return [c for c in self.columns if name.lower() in c.lower()]

pl.DataFrame.lookup = lookup

and use it like so

df = pl.DataFrame({"apple":[1], "pear":[2]})
assert df.lookup("app") == ["apple"]

Example 2: change the formatting of TtestResult

We may want to display the result differently than the default e.g. with a theme or formatting. We can overwrite the TtestResult class in the global scope, but here we do it with a context manager.

import contextlib
from scipy.stats._stats_py import TtestResult

@contextlib.contextmanager
def add_html_repr_to_ttest():

    original_repr_html = getattr(TtestResult, '_repr_html_', None)

    def custom_repr_html(self):
        ...
        return ...

    setattr(TtestResult, '_repr_html_', custom_repr_html)

    try:
        yield
    finally:
        if original_repr_html is None:
            delattr(TtestResult, '_repr_html_')
        else:
            setattr(TtestResult, '_repr_html_', original_repr_html)

and use it like so

from scipy.stats import ttest_ind

with add_html_repr_to_ttest():
    result = ttest_ind([1, 2, 3], [4, 5, 6])
    display(result)