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

问题描述 投票:0回答:1

[如何使用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类型没有断言语句。语句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 typescript pycharm python-typing
1个回答
0
投票

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

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

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.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保留在生产环境中。您的同事可能会或可能不会认为这更易读,这取决于他们对Python中类型提示的熟悉程度。

© www.soinside.com 2019 - 2024. All rights reserved.