def get_color_mapper_by_range(range_map, property_getter):
    """Return function to map colors into specific ranges.

    Such ranges are arbitrary ranges defined for a requested
    property.

    Parameters
    ==========

    range_map (dict)
        a dict where each key is a string representing
        a name for the specific range and the respective
        value is a range object (or other iterable with
        integers) representing the possible full values
        the property of a color can assume to be considered
        a member of that range;

        note that the "full value" of the property is used,
        rather than its "unit value" (its value in the
        unit interval).

        that is, the value is used for membership test
        (using the 'in' operation);

    property_getter (callable)
        callable which, given a color, returns the value
        of the requested property;

        in other words, the property requested is chosen
        by passing the appropriate getter.
    """
    ### define the color mapper function

    def color_mapper(colors):
        """Map colors according to specified settings.

        Parameters
        ==========

        colors (iterable of colors)
            we iterate over this argument, append each color
            to its corresponding range depending on the
            value of the requested property;

            each color is a sequence of integers in the
            range(256), representing the values of the
            red, green and blue channel of a color;
            a fourth integer may also be present,
            representing the value for the color's alpha
            channel.
        """
        ### create an ordered dict and fill it using names
        ### provided in the range map as the keys and
        ### empty lists as values

        name_to_list = OrderedDict()
        for name in range_map:
            name_to_list[name] = []

        ### iterate over the given colors, appending them to
        ### the appropriate lists depending on the value of
        ### the requested property, that is, depending on
        ### which range they fit

        for rgba_color in colors:

            ### retrieve value of the property (it is in its
            ### unit form here, that is, in the unit interval)
            property_value = property_getter(rgba_color)

            ### iterate over the items from the range map,
            ### until you find the item whose range has the
            ### value we retrieved from the property

            for name, range_obj in range_map.items():
                if property_value in range_obj:
                    break

            ### now that we found the range in which our
            ### property value fits, we append the color
            ### to the list associated with the name of
            ### that range
            name_to_list[name].append(rgba_color)

        ### once finished, return the dictionary we created
        return name_to_list

    ### return the defined color mapper function
    return color_mapper
Return function to map colors into specific ranges.

    Such ranges are arbitrary ranges defined for a requested
    property.

    Parameters
    ==========

    range_map (dict)
        a dict where each key is a string representing
        a name for the specific range and the respective
        value is a range object (or other iterable with
        integers) representing the possible full values
        the property of a color can assume to be considered
        a member of that range;

        note that the "full value" of the property is used,
        rather than its "unit value" (its value in the
        unit interval).

        that is, the value is used for membership test
        (using the 'in' operation);

    property_getter (callable)
        callable which, given a color, returns the value
        of the requested property;

        in other words, the property requested is chosen
        by passing the appropriate getter.
    
nodezator/ourstdlibs/color/utils.py