Basic Usage
This guide covers the fundamental operations with I24 and U24 types.
Creating Instances
From Python int
The most common way to create I24 and U24 values is from Python integers:
from i24 import I24, U24
# Create signed 24-bit integer
signed = I24(1000)
print(signed) # I24(1000)
# Create unsigned 24-bit integer
unsigned = U24(50000)
print(unsigned) # U24(50000)
Value Range Validation
The constructors automatically validate that values are within the valid range:
from i24 import I24, U24
# Valid ranges:
# I24: -8,388,608 to 8,388,607
# U24: 0 to 16,777,215
try:
# This will raise ValueError (out of range)
invalid = I24(10_000_000)
except ValueError as e:
print(f"Error: {e}")
try:
# This will raise ValueError (negative for unsigned)
invalid = U24(-100)
except ValueError as e:
print(f"Error: {e}")
From Bytes
Create values from byte sequences with configurable byte order:
from i24 import I24, U24
# Little-endian bytes
bytes_le = bytes([0x00, 0x10, 0x00])
value = I24.from_bytes(bytes_le, byteorder='little')
print(value.to_int()) # 4096
# Big-endian bytes
bytes_be = bytes([0x00, 0x10, 0x00])
value = I24.from_bytes(bytes_be, byteorder='big')
print(value.to_int()) # 4096
# Native byte order (platform-dependent)
value = I24.from_bytes(bytes([0x01, 0x02, 0x03]), byteorder='native')
Converting to Python Types
To int
Convert 24-bit integers to Python int:
from i24 import I24, U24
signed = I24(-1000)
unsigned = U24(2000)
# Explicit conversion
int_val = signed.to_int()
print(int_val) # -1000
# Using __int__() magic method
int_val = int(unsigned)
print(int_val) # 2000
To Bytes
Convert to byte sequences:
from i24 import I24
value = I24(0x123456)
# Convert to little-endian bytes
le_bytes = value.to_bytes(byteorder='little')
print(le_bytes) # [86, 52, 18]
# Convert to big-endian bytes
be_bytes = value.to_bytes(byteorder='big')
print(be_bytes) # [18, 52, 86]
# Native byte order
native_bytes = value.to_bytes(byteorder='native')
Comparisons
I24 and U24 support all standard comparison operators:
from i24 import I24, U24
a = I24(100)
b = I24(200)
c = I24(100)
# Equality
print(a == c) # True
print(a == b) # False
print(a != b) # True
# Ordering
print(a < b) # True
print(a <= c) # True
print(b > a) # True
print(b >= a) # True
# Works with U24 too
x = U24(1000)
y = U24(2000)
print(x < y) # True
String Representations
from i24 import I24, U24
value = I24(12345)
# str() - returns just the number
print(str(value)) # "12345"
# repr() - returns the full representation
print(repr(value)) # "I24(12345)"
# Works in f-strings
print(f"Value: {value}") # "Value: 12345"
Hashing
I24 and U24 are hashable and can be used in sets and as dictionary keys:
from i24 import I24, U24
# Use in sets
values = {I24(100), I24(200), I24(100)}
print(len(values)) # 2 (duplicates removed)
# Use as dictionary keys
mapping = {
I24(1): "one",
I24(2): "two",
U24(100): "hundred"
}
print(mapping[I24(1)]) # "one"
Immutability
Both I24 and U24 are frozen (immutable) types. Once created, their values cannot be changed:
from i24 import I24
value = I24(100)
# This would raise an error if you tried:
# value.value = 200 # AttributeError: can't set attribute
# Instead, create a new instance
new_value = I24(200)
Class Attributes
Access minimum and maximum values:
from i24 import I24, U24
# I24 range
print(I24.min_value) # I24(-8388608)
print(I24.max_value) # I24(8388607)
# U24 range
print(U24.min_value) # U24(0)
print(U24.max_value) # U24(16777215)
Type Checking
from i24 import I24, U24
value = I24(100)
# Check type
print(isinstance(value, I24)) # True
print(isinstance(value, U24)) # False
# Type hints work properly
def process_signed(val: I24) -> int:
return val.to_int() * 2
result = process_signed(value)
print(result) # 200