Super-fast and clean conversions to numbers with flexible error handling and high-performance drop-in replacements for Python's built-in number conversion functions.
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Additional utility functions for type analysis and deprecated functions maintained for backward compatibility. These functions provide specialized capabilities for introspecting numeric types and supporting legacy code.
Analyzes input to determine what numeric type it represents without performing conversion, useful for type introspection and conditional processing.
def query_type(
x,
*,
allow_inf=False,
allow_nan=False,
coerce=False,
allowed_types=None,
allow_underscores=False
):
"""
Determine the numeric type of input without conversion.
Parameters:
- x: Input to analyze (any type)
- allow_inf: Allow infinity values (default: False)
- allow_nan: Allow NaN values (default: False)
- coerce: Enable type coercion analysis (default: False)
- allowed_types: Sequence of allowed types to check against (optional)
- allow_underscores: Allow underscores in numeric strings (default: False)
Returns:
- Type[int] | Type[float] | Type[input] | None: Detected numeric type or None
"""from fastnumbers import query_type
# Basic type detection
query_type('123') # <class 'int'>
query_type('123.45') # <class 'float'>
query_type(456) # <class 'int'>
query_type(78.9) # <class 'float'>
query_type('invalid') # <class 'str'> (original type)
# Coercion analysis
query_type('123.0') # <class 'str'> (no coercion)
query_type('123.0', coerce=True) # <class 'int'> (would coerce to int)
query_type(456.0) # <class 'float'>
query_type(456.0, coerce=True) # <class 'int'> (would coerce to int)
# Special value handling
query_type('inf') # <class 'str'> (inf not allowed)
query_type('inf', allow_inf=True) # <class 'float'> (inf allowed)
query_type('nan', allow_nan=True) # <class 'float'> (nan allowed)
# Type filtering
allowed = [int, float]
query_type('123', allowed_types=allowed) # <class 'int'>
query_type('invalid', allowed_types=allowed) # None (not in allowed types)
# Formatting support
query_type('1_000', allow_underscores=True) # <class 'int'>
query_type('1_000') # <class 'str'> (underscores not allowed)# Conditional processing based on type
def smart_convert(value):
detected_type = query_type(value, coerce=True, allow_inf=True, allow_nan=True)
if detected_type == int:
return int(value)
elif detected_type == float:
return float(value)
else:
return value # Keep as original type
# Type validation in data pipelines
def validate_numeric_column(values, expected_type):
"""Validate that all values can be converted to expected type."""
allowed_types = [expected_type]
for i, value in enumerate(values):
if query_type(value, allowed_types=allowed_types) is None:
raise ValueError(f"Value at index {i} cannot be converted to {expected_type.__name__}: {value}")
return True
# Schema inference
def infer_column_type(values):
"""Infer the best numeric type for a column of data."""
type_counts = {'int': 0, 'float': 0, 'other': 0}
for value in values:
detected = query_type(value, coerce=True, allow_inf=True, allow_nan=True)
if detected == int:
type_counts['int'] += 1
elif detected == float:
type_counts['float'] += 1
else:
type_counts['other'] += 1
if type_counts['other'] > 0:
return str # Mixed types, keep as string
elif type_counts['float'] > 0:
return float # Any floats mean float column
else:
return int # All integersThese functions are maintained for backward compatibility but are deprecated in favor of their check_* equivalents. They provide the same functionality with slightly different parameter names and defaults.
def isreal(
x,
*,
str_only=False,
num_only=False,
allow_inf=False,
allow_nan=False,
allow_underscores=True
) -> bool:
"""
DEPRECATED: Use check_real() instead.
Check if input represents a real number.
"""def isfloat(
x,
*,
str_only=False,
num_only=False,
allow_inf=False,
allow_nan=False,
allow_underscores=True
) -> bool:
"""
DEPRECATED: Use check_float() instead.
Check if input represents a float.
"""def isint(
x,
*,
str_only=False,
num_only=False,
base=0,
allow_underscores=True
) -> bool:
"""
DEPRECATED: Use check_int() instead.
Check if input represents an integer.
"""def isintlike(
x,
*,
str_only=False,
num_only=False,
allow_underscores=True
) -> bool:
"""
DEPRECATED: Use check_intlike() instead.
Check if input represents an integer-like value.
"""# OLD (deprecated)
from fastnumbers import isreal, isfloat, isint, isintlike
isreal('123', str_only=True) # DEPRECATED
isfloat('123.45', num_only=True) # DEPRECATED
isint('123', str_only=True) # DEPRECATED
isintlike('123.0') # DEPRECATED
# NEW (recommended)
from fastnumbers import check_real, check_float, check_int, check_intlike
from fastnumbers import STRING_ONLY, NUMBER_ONLY
check_real('123', consider=STRING_ONLY) # RECOMMENDED
check_float('123.45', consider=NUMBER_ONLY) # RECOMMENDED
check_int('123', consider=STRING_ONLY) # RECOMMENDED
check_intlike('123.0') # RECOMMENDEDAccess to the package version for compatibility checking and logging.
__version__: str # Package version string (e.g., "4.0.1")import fastnumbers
# Version checking
print(f"Using fastnumbers version: {fastnumbers.__version__}")
# Compatibility checking
def check_fastnumbers_version(min_version):
"""Check if fastnumbers version meets minimum requirement."""
from packaging import version
current = version.parse(fastnumbers.__version__)
required = version.parse(min_version)
return current >= required
# Feature availability
def has_underscore_support():
"""Check if version supports underscore parameter."""
return check_fastnumbers_version("2.0.0")
# Logging setup
import logging
logging.info(f"Initialized fastnumbers {fastnumbers.__version__}")def process_mixed_data(values):
"""Process mixed numeric/string data intelligently."""
results = []
for value in values:
value_type = query_type(value, coerce=True, allow_inf=True, allow_nan=True)
if value_type == int:
results.append(('integer', int(value)))
elif value_type == float:
results.append(('float', float(value)))
else:
results.append(('string', str(value)))
return resultsdef validate_and_convert(data, target_type):
"""Validate data can be converted before attempting conversion."""
# Pre-validate all data
allowed_types = [target_type]
invalid_indices = []
for i, value in enumerate(data):
if query_type(value, allowed_types=allowed_types) is None:
invalid_indices.append(i)
if invalid_indices:
raise ValueError(f"Invalid values at indices: {invalid_indices}")
# Convert validated data
if target_type == int:
return [int(x) for x in data]
elif target_type == float:
return [float(x) for x in data]
else:
return datadef evolve_schema(old_data, new_requirements):
"""Evolve data schema based on new type requirements."""
evolved_data = []
for value in old_data:
# Analyze current type
current_type = query_type(value, coerce=True)
# Convert based on new requirements
if new_requirements == 'strict_int' and current_type != int:
raise ValueError(f"Cannot convert {value} to strict int")
elif new_requirements == 'numeric' and current_type in [int, float]:
evolved_data.append(float(value) if current_type == int else value)
else:
evolved_data.append(value)
return evolved_dataThese utility functions enable sophisticated numeric type analysis and provide pathways for migrating legacy code to the modern fastnumbers API.
Install with Tessl CLI
npx tessl i tessl/pypi-fastnumbers