Fair enough.
The syntactic awkwardness, then, explains why numbers don't have an
evolved set of methods (unlike strings).
But numbers do have an evolved set of methods.
py> [name for name in vars(int) if not name.startswith("_")]
['numerator', 'imag', 'to_bytes', 'from_bytes', 'bit_length', 'real',
'conjugate', 'denominator']
py> [name for name in vars(float) if not name.startswith("_")]
['fromhex', 'imag', 'as_integer_ratio', 'is_integer', 'hex', 'real',
'conjugate']
py> [name for name in vars(complex) if not name.startswith("_")]
['imag', 'real', 'conjugate']
To say nothing of these numbers:
py> from decimal import Decimal
py> [name for name in vars(Decimal) if not name.startswith("_")]
['canonical', 'exp', 'to_integral_value', 'logical_xor', 'imag',
'same_quantum', 'log10', 'max_mag', 'is_snan', 'to_eng_string', 'ln',
'is_normal', 'min', 'is_subnormal', 'to_integral_exact', 'is_nan',
'logb', 'is_qnan', 'logical_or', 'radix', 'real', 'max', 'normalize',
'as_tuple', 'is_canonical', 'is_zero', 'copy_negate', 'min_mag',
'next_plus', 'is_finite', 'number_class', 'scaleb', 'is_signed',
'compare_total', 'next_toward', 'adjusted', 'fma', 'rotate',
'logical_and', 'from_float', 'to_integral', 'next_minus',
'remainder_near', 'compare_signal', 'quantize', 'is_infinite',
'copy_sign', 'shift', 'compare_total_mag', 'copy_abs', 'compare',
'conjugate', 'logical_invert', 'sqrt']
That's more methods than strings have:
py> len([name for name in vars(Decimal) if not name.startswith("_")])
54
py> len([name for name in vars(str) if not name.startswith("_")])
44