Search code examples
pythonpint

Why is ureg(0) equal to 1?


The following code prints '1 dimensionless':

import pint
ureg=pint.UnitRegistry()
print(ureg(0.))

Why, Pint?


Solution

  • "Calling" a UnitRegistry object is equivalent to calling parse_expression on it. parse_expression expects to receive a str, and it has a special case for the empty string, which is to return it as a Quantity(1) (the 1 dimensionless you see).

    In this case, you happened to hit a minor flaw in the duck-typing: It expects a string, but doesn't actually verify that it received one. Then it converts any falsy value to Quantity(1) with the code:

    if not input_string:
        return self.Quantity(1)
    

    so any zero-valued number (or None, or empty sequence, or other falsy thing) becomes Quantity(1). Had you passed it a truthy expression of an unexpected type, the parser would have gotten involved and raised an exception, but falsy values never even reach the parser.

    I'm not clear on why the empty expression should be a Quantity(1), but the authors explicitly put that check in there, so it must have been intended.

    In short, don't pass non-strings to the function. They'll fail silently when falsy, and raise an exception for anything else (when it assumes they're a str and it tries to call str methods on them).