This class or closure to clamp at specific bounds is nice. But I want to clamp based on runtime values for upper/lower fairly often. A function is much better for that use.

On Wed, Jul 8, 2020, 11:22 AM Jonathan Fine <> wrote:
Hi All

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

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
                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.

Python-ideas mailing list --
To unsubscribe send an email to
Message archived at
Code of Conduct: