def check_range_and_coerce_step(low, high, step=None):
    """

    :param low:
    :param high:
    :param step:
    :return:

        >>> checker = check_range_and_coerce_step(1, 10)
        >>> checker(1), checker(5), checker(10)
        (1, 5, 10)
        >>> checker(11)
        Traceback (most recent call last):
        ...
        ValueError: 11 not in range (1, 10)
        >>> checker = check_range_and_coerce_step(1, 10, 1)
        >>> checker(1), checker(5.4), checker(10)
        (1, 5, 10)

    """
    def _inner(value):
        if not (low <= value <= high):
            raise ValueError('{} not in range ({}, {})'.format(value, low, high))
        if step:
            value = round((value - low) / step) * step + low
        return value

    return _inner