【问题标题】:Avoid PyCharm Type-Warning when using typing.NewType使用 typing.NewType 时避免 PyCharm 类型警告
【发布时间】:2020-09-05 15:38:24
【问题描述】:

在与 PyCharm 合作慢慢掌握 typing 的窍门后,我发现自己经常使用该软件包。我喜欢它的灵活性以及它如何适应几乎任何用例。

在使用包时(也因为它非常有用),我考虑为我从数据库中获取的某些str id 创建一个“包装器类型”,并在整个项目中用作字典键。

这样,如果一个函数使用直接从数据库获取的 id 作为键来传递字典,则类型提示不仅会提示所需的类型,还会提供有关数据流和键结构的一些信息,如果不只是一个,但使用了两个或多个数据库 ID,以组成一个字典键。

我认为选择的工具是NewType,因为它实际上创建了一个新类型,其名称可以显示在 PyCharms 工具提示中(与TypeAlias 或只是PrimaryKey = str 不同)。但是,正如 documentation 中所预测的那样,PyCharm 的静态类型检查器不接受创建的 NewType 作为 str 并引发类型警告。

"Expect '{NewType xy}' got 'str' instead".

所以我的问题是:有什么办法解决这个问题吗?

# instead of:
some_info: Mapping[Tuple[str, str], List[Any]] = dict()  # obviously works

# it'd look like this:
PrimaryKeyA = NewType('PrimaryKeyA', str)
PrimaryKeyB = NewType('PrimaryKeyB', str)

some_info: Mapping[Tuple[PrimaryKeyA, PrimaryKeyB], List[Any]] = dict()

some_info['AKey_01', 'BKey_01'] = 'example_data'  # raises type warning

# I could do: 
some_info[PrimaryKeyA('AKey_01'), PrimaryKeyB('BKey_01')] = 'example_data'
# But that doesn't feel more readable

在我目前参与的项目中,这将极大地提高可读性,因为整个事情正在收集不同详细级别的内容,每个级别都由数据库主键标识。但如果我不能让它与 PyCharm 一起工作,我认为这不值得。

【问题讨论】:

  • 您需要显式创建 PrimaryKeyA 类型的“AKey_01”,否则 NewType 的行为与类型别名相同。这个想法是你在有限的地方创建新类型的实例,这样你就知道在传递它之后你有什么。

标签: python python-3.x pycharm python-typing


【解决方案1】:

NewType 的主要目标是帮助检测逻辑错误,例如不应该传入 PrimaryKey。所以我认为最好的方法是你最后的表现。

some_info[PrimaryKeyA('AKey_01'), PrimaryKeyB('BKey_01')] = 'example_data'

您可以做的一件事是在程序中定义这些字符串。

key_1 = PrimaryKeyA('AKey_01')
key_2 = PrimaryKeyB('BKey_01')

some_info[key_1, key_2]

或根据上下文将它们作为函数的参数。因为这应该有效:

def foo(key_1: PrimaryKeyA, key_2: PrimaryKeyB) -> None:
    some_info[key_1, key_2] = 'example_data'

实际上并不是运行时的新类型

因为它实际上创建了一个具有名称的新类型

最后我只想指出这实际上是不正确的,至少在运行时不正确。类型检查器会将其视为新类型,是的,但在运行时它只会返回给它的任何内容。

In [1]: from typing import NewType             

In [2]: A = NewType("A", int)                  

In [3]: A("abc")       
Out[3]: 'abc'

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-05-22
    • 2019-10-04
    • 2019-12-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-27
    相关资源
    最近更新 更多