def irange(start, stop, step=1):
    """
    Iterate over all values greater or equal than `start` and less than `stop`.
    (Or the reverse, if `step < 0`.)

    Example::

      >>> list(irange(1, 5))
      [1, 2, 3, 4]
      >>> list(irange(0, 8, 3))
      [0, 3, 6]
      >>> list(irange(8, 0, -2))
      [8, 6, 4, 2]

    Unlike the built-in `range` function, `irange` also accepts
    floating-point values::

      >>> list(irange(0.0, 1.0, 0.5))
      [0.0, 0.5]

    Also unlike the built-in `range`, *both* `start` and `stop` have
    to be specified::

      >>> try:
      ...   irange(42)
      ... except TypeError:
      ...   print("missing required argument!")
      missing required argument!

    Of course, a null `step` is not allowed::

      >>> try:
      ...   list(irange(1, 2, 0))
      ... except AssertionError as err:
      ...   assert 'Null step in irange.' in str(err)
    """
    assert float(step) != 0.0, 'Null step in irange.'
    value = start
    if step > 0:
        while value < stop:
            yield value
            value += step
    else:
        while value > stop:
            yield value
            value += step
