Hi All

This is related to discussion https://mail.python.org/archives/list/python-ideas@python.org/thread/KWAOQFSV3YJYQV2Y5JXGXFCXHJ3WFLRS/#ZT3OBOPNIMXQ2MU7N5RFBL5AJSYRZJ6Q

In Python, lists don't have a join method. Instead, it's strings that have the join method. Hence we have:
    >>> ', '.join('abcde')
    'a, b, c, d, e'

The intermediate method we can save and store and use again.
    >>> joiner = ', '.join
    >>> joiner('fghijk')
    'f, g, h, i, j, k'

We can do something similar when clamping, clipping or trimming a value. For example, suppose we want limits on the room temperature, that the thermostat cannot override.
    >>> aircon_clipper = Clamper(50, 80)

    >>> thermostat_temp = 40
    >>> target_temp = aircon_temp_clipper(thermostat_temp)
    >>> target_temp
    50

What I like best about this is that the name of the function -- aircon_temp_clipper -- gives the reason for the clipping (or clamping). And this name can be chosen to suit the domain. I also like that it wraps the high and low values (50 and 80) as data used by a method.

Here's an implementation of Clamper.

    class Clamper:
        def __init__(self, lo, hi):

            if not lo <= hi:
                raise ValueError
            self._lo = lo
            self._hi = hi

        def __call__(self, num):
            lo, hi = self._lo, self._hi

            at_least_lo = (lo <= num)
            at_most_hi = (hi >= num)

            if at_least_lo and at_most_hi:
                return num
            elif at_least_lo:
                return hi
            elif at_most_hi:
                return lo
            else:
                raise ValueError

If performance is important to you, you could instead use a closure to create a function. This would also allow you to provide a docstring.

I hope this helps at least some of the people some of the time.

-- 
Jonathan