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

2024-09-28 23:38:51 发布

您现在位置:Python中文网/ 问答频道 /正文

如何在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)禁止使用裸断言语句的项目代码样式


Tags: 代码in声明类型ifisdef错误
1条回答
网友
1楼 · 发布于 2024-09-28 23:38:51

只要您使用的是Python3.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(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

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

相关问题 更多 >