简体   繁体   English

使用 typing.NewType 时避免 PyCharm 类型警告

[英]Avoid PyCharm Type-Warning when using typing.NewType

After slowly getting the hang of typing in collaboration with PyCharm, I find myself using the package a lot.在与 PyCharm 合作慢慢掌握打字的窍门后,我发现自己经常使用 package。 I like its flexibility and how it can be adapted to almost any use case.我喜欢它的灵活性以及它如何适应几乎任何用例。

While playing with the package (and also because it'd be really useful) I thought about creating a "wrapper-type" for certain str ids I get from a database and use as dictionary keys throughout the project.在使用 package 时(也因为它非常有用),我考虑为我从数据库中获取的某些str id 创建一个“包装器类型”,并在整个项目中用作字典键。

That way, if a function was passing a dictionary using ids gotten directly from the database as keys, the type hints would not just hint at the required type, but also provide some information on the dataflow and key structures, if not just one, but two or more database ids were used, to make up a dictionary key.这样,如果 function 使用直接从数据库中获取的 id 作为键传递字典,则类型提示不仅会提示所需的类型,还会提供有关数据流和键结构的一些信息,如果不仅仅是一个,而是使用了两个或多个数据库 ID 来组成字典键。

I thought the facility of choice would be NewType , since it actually creates a new type with a name that can be shown in PyCharms tooltip (Unlike TypeAlias or just PrimaryKey = str ).我认为选择的工具是NewType ,因为它实际上创建了一个新类型,其名称可以显示在 PyCharms 工具提示中(与TypeAlias或只是PrimaryKey = str不同)。 However, as predicted in the documentation , PyCharm's static type checker does not accept the created NewType as str and raises a type warning.但是,正如文档中所预测的那样,PyCharm 的 static 类型检查器不接受创建的NewType作为str并引发类型警告。

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

So my question: Is there any way around that?所以我的问题是:有没有办法解决这个问题?

# 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

In the project I'm currently involved with, this would be a giant improvement for readability since the whole thing is collecting stuff on different levels of detail, each level identified by a database primary key.在我目前参与的项目中,这将是可读性的巨大改进,因为整个事情正在收集不同详细级别的内容,每个级别都由数据库主键标识。 But if I can't get it to work with PyCharm, I don't think it'd be worth the trouble.但如果我不能让它与 PyCharm 一起工作,我认为这不值得麻烦。

The main goal of NewType is to help detect logical errors, like not passing in a PrimaryKey were you should. NewType的主要目标是帮助检测逻辑错误,例如不应该传入PrimaryKey so I think the best way to do it is how you showed last.所以我认为最好的方法是你最后展示的方式。

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

one thing you could do is define those strings before in the program.您可以做的一件事是在程序之前定义这些字符串。

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

some_info[key_1, key_2]

or take them as arguments to a function depending on the context.或根据上下文将它们作为 arguments 到 function 。 as this should work:因为这应该有效:

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

Not actually a new type on runtime实际上不是运行时的新类型

since it actually creates a new type with a name因为它实际上创建了一个具有名称的新类型

lastly I just want to point out that this is actually not correct, atleast not at runtime.最后我只想指出这实际上是不正确的,至少在运行时不是。 type checkers will treat it as a new type yes, but at runtime it just returns whatever given to it.类型检查器会将其视为新类型,是的,但在运行时它只会返回给它的任何内容。

In [1]: from typing import NewType             

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

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM