LoopInt is a lightweight Python library that provides a cyclic integer type with precise range semantics [left; right) and natural integer-like behavior.
It behaves like a regular integer but wraps around within a fixed interval. This makes it useful for cyclic counters, circular buffers, modular arithmetic, clock-like values, and more.
- Fixed interval semantics: [left; right)
- Modular wrap-around on
+,-,+=,-= - Behaves like
intin:- comparisons
- hashing
- indexing (
__index__) - formatting (
__format__) int()conversion
- Safe arithmetic:
LoopInt + intsupportedLoopInt += intsupported- Adding two
LoopIntobjects is intentionally forbidden
- Fully typed (Python β₯ 3.12)
pip install loopintOr with uv:
uv add loopintfrom loopint import LoopInt
x = LoopInt(0, right=5)
print(int(x)) # 0
x += 7
print(int(x)) # 2 (wrap-around: 7 % 5 == 2)
y = x + 10
print(int(y)) # 2 (non-mutating)
assert x == 2
assert y == xx = LoopInt(0, right=2, left=-1)
print(int(x)) # 0
x += 1
print(int(x)) # 1
x += 2 # wraps in [-1; 2)
print(int(x)) # 0Create a cyclic integer constrained to the interval [left; right) with modular wrap-around.
Parameters:
currentβ initial value (any integer-like object supporting__index__)rightβ exclusive upper boundleftβ inclusive lower bound (default:0)
Interval semantics:
value β [left; right)
span = right β left
value = left + ((current β left) mod span)
Returns the visible integer value of the LoopInt instance.
Equivalent to:
int(loopint_instance)Example:
x = LoopInt(5, right=8, left=2)
assert x.value == 5Returns the inclusive lower bound of the interval.
Example:
LoopInt(0, right=5, left=-2).left # β -2Returns the exclusive upper bound of the interval.
Example:
LoopInt(0, right=5).right # β 5Size of the interval:
span = right - left
Example:
LoopInt(0, right=5, left=2).span # β 3Return the value as a string. Equivalent to:
str(int(self))Example:
x = LoopInt(4, right=10)
x.to_string() # β "4"Non-mutating addition with wrap-around.
x + n # returns a new LoopIntIn-place addition (+=) with wrap-around.
x += 3Non-mutating subtraction.
In-place subtraction (-=).
Modular negation:
int(-x) == (-int(x)) mod span
Example:
x = LoopInt(1, right=5)
y = -x # β 4Enables: int + LoopInt.
Example:
3 + LoopInt(2, right=5) # β 0Implements: other - self using modular arithmetic.
other - x == -(x - other)
Example:
3 - LoopInt(1, right=5) # β 2
0 - LoopInt(1, right=5) # β 4LoopInt compares equal to anything whose integer value equals int(self).
Examples:
LoopInt(0, right=5) == 0 # True
LoopInt(3, right=10) == LoopInt(3, right=100) # TrueHash is consistent with int(self):
hash(LoopInt(3, right=10)) == hash(3)pytest .Both unit tests and property-based tests (Hypothesis) are included.
MIT License.
Contributions are welcome! Feel free to open issues or pull requests.