1

以下代码打印“1无量纲”:

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

为什么,品脱?

4

2 回答 2

2

“调用”一个UnitRegistry对象相当于调用parse_expressionparse_expression期望收到 a str,并且它有一个空字符串的特殊情况,即将它作为 aQuantity(1)1 dimensionless你看到的)返回。

在这种情况下,您碰巧遇到了鸭子打字的一个小缺陷:它需要一个字符串,但实际上并没有验证它是否收到了一个字符串。然后它将任何虚假值转换Quantity(1)为代码:

if not input_string:
    return self.Quantity(1)

所以任何零值数(或None,或空序列,或其他虚假事物)变为Quantity(1)。如果你向它传递了一个意外类型的真值表达式,解析器就会介入并引发异常,但假值甚至永远不会到达解析器。

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

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

于 2018-10-05T19:26:09.367 回答
2

看起来像包中的错误/限制。

传递整数(不同于 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创建pint一个1类(或其他任何含义),就像您通过"". 通过1允许到达下一行,该行崩溃。

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

    if not isinstance(input_string,str):
        raise Exception("a string is required")
于 2018-10-05T19:26:34.763 回答