为什么 ureg(0) 等于 1?

Why is ureg(0) equal to 1?

以下代码打印'1 dimensionless':

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

为什么,Pint?

"Calling"一个UnitRegistry对象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)(你看到的1 dimensionless)。

在这种情况下,您碰巧遇到了鸭子类型的一个小缺陷:它需要一个字符串,但实际上并没有验证它是否收到了一个字符串。然后 it converts any falsy value to Quantity(1) 代码:

if not input_string:
    return self.Quantity(1)

所以任何零值数字(或 None,或空序列,或其他虚假的东西)变成 Quantity(1)。如果您向它传递了一个意外类型的真实表达式,解析器就会参与进来并引发异常,但虚假值甚至永远不会到达解析器。

我不清楚为什么空表达式应该是一个 Quantity(1),但作者明确地把检查放在那里,所以它一定是有意的。

简而言之,不要将非字符串传递给函数。它们会在 falsy 时默默地失败,并为其他任何事情引发异常(当它假设它们是 str 并尝试对它们调用 str 方法时)。

包装中看起来像 bug/limitation。

传递整数(不同于 0)时 pint 崩溃:

>>> ureg(1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Python34\lib\site-packages\pint\registry.py", line 837, in parse_expression
    input_string = string_preprocessor(input_string)
  File "C:\Python34\lib\site-packages\pint\util.py", line 579, in string_preprocessor
    input_string = input_string.replace(",", "")
AttributeError: 'int' object has no attribute 'replace'

registry.py

def parse_expression(self, input_string, case_sensitive=True, **values):
    """Parse a mathematical expression including units and return a quantity object.

    Numerical constants can be specified as keyword arguments and will take precedence
    over the names defined in the registry.
    """

    if not input_string:
        return self.Quantity(1)

    input_string = string_preprocessor(input_string)  # should not be called with something else than string

它崩溃是因为程序包试图对非字符串执行字符串操作,而该字符串应该是字符串。但是测试是 if not input_string 所以 0.0 make pint 创建一个 1 class (或任何意思),就像你通过 "".传递 1 允许到达下一行,这会崩溃。

它只是缺少类型检查,例如:

    if not isinstance(input_string,str):
        raise Exception("a string is required")