How to parse a number as either an int or a float, depending on required precision?

Viewed 209

Requirements:

  1. Input can be either string or number
  2. If input could be treated as an int without loss of precision, cast to int
  3. If input could be treated as a float, cast to float

Here is the section of code where I am using this.

def make_operand(symbol, left=None, right=None):
    valid_symbols = ['*', '/', '+', '-']
    if symbol in valid_symbols:
        return Operand(symbol, left, right)

    as_int = re.compile("^-?[0-9]+$").match(str(symbol))
    as_float = re.compile("^[-+]?[0-9]*\.?[0-9]+$").match(str(symbol))

    as_number = int(symbol) if as_int else float(symbol) if as_float else None

    if as_number:
        return NumericOperand(as_number)

    raise ValueError("Invalid symbol or number")

This works but it looks messy and smells wrong.

An implementation using try blocks also works, but seems less simple:

    as_number = None
    try:
        as_float = float(symbol)
    except ValueError:
        as_float = None

    if as_float:
        as_int = int(as_float)
        as_number = as_int if as_int == as_float else as_float

    if as_number:
        return NumericOperand(as_number)

    raise ValueError("Invalid symbol or number")

Is there a better approach, or is one of these close to the Pythonic method of doing things?

2 Answers
Related