gpt4 book ai didi

python - 使用类型注释来缩小已声明的 Python 变量的类型

转载 作者:行者123 更新时间:2023-11-30 21:50:49 25 4
gpt4 key购买 nike

如何在 Python 中使用类型注释来更改或缩小已声明变量的类型,从而使 pycharm 或其他类型感知系统能够理解新类型。

例如,我可能有两个类:

class A:
is_b = False
...

class B(A):
is_b = True

def flummox(self):
return '?'

以及其他地方的另一个函数:

def do_something_to_A(a_in: A):
...
if a_in.is_b:
assert isinstance(a_in, B) # THIS IS THE LINE...
a_in.flummox()

只要我有 assert 语句,PyCharm 就会理解我已将 a_in 缩小为 B 类,并且不会提示 .flummox ()。如果没有它,就会出现诸如 a_in has no method Flummox 之类的错误/警告。

我的问题是,是否有 PEP 484(或后继)方式来显示 a_in (最初可能是 A 类型或 B 类型或其他类型)现在是 B 类型没有assert语句。语句 b_in : B = a_in 也会给出类型错误。

在 TypeScript 中我可以做这样的事情:

if a_in.is_b:
const b_in = <B><any> a_in;
b_in.flummox()

// or

if a_in.is_b:
(a_in as B).flummox()

我不想使用断言行有两个主要原因:(1) 速度对于这部分代码非常重要,并且每次该行都有一个额外的 is_instance 调用运行速度会减慢太多,并且 (2) 项目代码风格禁止裸露的断言语句。

最佳答案

只要您使用 Python 3.6+,您就可以使用与“声明”变量类型而不初始化变量类型相同的语法任意“重新注释”变量的类型 ( PEP 526 )。

在您提供的示例中,以下代码段具有您期望的行为:

def do_something_to_A(a_in: A):
...
if a_in.is_b:
a_in: B
a_in.flummox()

我已经测试过 PyCharm 2019.2 可以正确检测到该技术。

值得注意的是,这不会产生运行时成本,因为无论是否添加此注释语句都会生成相同的字节码。鉴于以下定义,

def do_something_with_annotation(a_in: A): 
if a_in.is_b:
a_in: B
a_in.flummox()


def do_something_without_annotation(a_in: A):
if a_in.is_b:
a_in.flummox()

dis生成以下字节码:

>>> dis.dis(do_something_with_annotation)
3 0 LOAD_FAST 0 (a_in)
2 LOAD_ATTR 0 (is_b)
4 POP_JUMP_IF_FALSE 14

5 6 LOAD_FAST 0 (a_in)
8 LOAD_ATTR 1 (flummox)
10 CALL_FUNCTION 0
12 POP_TOP
>> 14 LOAD_CONST 0 (None)
16 RETURN_VALUE
>>> dis.dis(do_something_without_annotation)
3 0 LOAD_FAST 0 (a_in)
2 LOAD_ATTR 0 (is_b)
4 POP_JUMP_IF_FALSE 14

4 6 LOAD_FAST 0 (a_in)
8 LOAD_ATTR 1 (flummox)
10 CALL_FUNCTION 0
12 POP_TOP
>> 14 LOAD_CONST 0 (None)
16 RETURN_VALUE

作为旁注,您还可以保留断言语句和 disable assertions在您的生产环境中,通过使用 -O 标志调用解释器。您的同事可能会或可能不会认为这更具可读性,具体取决于他们对 Python 中类型提示的熟悉程度。

关于python - 使用类型注释来缩小已声明的 Python 变量的类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60271719/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com