Python3:与变量关联的单位度量

Python3: unit measures associated to variables

作为一个有几十年历史的程序员,我从惨痛的教训中学到,物理值给变量加上标签是有意义的。在 C 或 C++ 中,我使用行内注释来完成:

C 中的代码

double /*MOhm*/ resistance(double R1 /*MOhm*/, double R2 /*MOhm*/){
    return R1+R2;
}

评论目的:输入是MOhm,输出也是MOhm。

是否有优雅的 Python 方式来做同样的事情?没有行内注释,怎么办呢?有一个可读的代码对我来说非常重要,它很容易被另一个人理解。

在 Python 中你应该使用函数 docstring describing the parameters and return values. For example, using sphinx 语法:

def resistance(r1: float, r2: float) -> float:
    """
    Calculate resistance.

    :param r1: resistance in MOhm
    :param r2: resistance in MOhm
    :returns: total resistance in MOhm
    """
    return r1 + r2

IDE 可以解析标准格式的文档字符串,为您提供有用的自动完成等功能。

要具体:定义一个类型(实际上是类型别名)来准确描述您的期望。

MOhm = float

def resistance(r1: MOhm, r2: MOhm) -> MOhm:
    return r1 + r2

(Python 3 确实允许使用 Unicode 标识符,因此您可以想象并编写

# That's M\u2126, M + OHM SIGN
MΩ = float

def resistance(r1: MΩ, r2: MΩ) -> MΩ:
    return r1 + r2

然而,U+03a9(Ω,希腊大写字母 OMEGA)和 U+2126(Ω,OHM SIGN)充其量很难区分,所以我会在实际中避免使用这种标识符代码。)


您可以更进一步,定义一个 真正的 新类型,mypy 等工具将执行该类型。但是,这样做会花费很少的 运行 时间。

from typing import NewType

Ohm = NewType("Ohm", float)
MOhm = NewType("MOhm", float)

def resistance(r1: MOhm, r2: MOhm) -> MOhm:
    return MOhm(r1 + r2)

x: Ohm = Ohm(3.0)
y: MOhm = MOhm(4.0)

# mypy error, resistance expects its first argument to have type MOHm, not OHm
print(resistance(x, y))

NewType 是定义 类 like

的辅助函数
class Ohm(float):
    pass

class MOhm(float):
    pass

在 运行 时,所有三个 类 行为相同。但是,像 mypy 这样的工具会将它们视为不同的 类,让您更加努力地确保 你的代码类型检查。当你不小心犯单位错误时更难 必须具体说明您传递的值。