python保存类型没有后缀py_pycharm-没有循环导入的Python类型提示

pycharm-没有循环导入的Python类型提示

我正试图将我的大班分成两部分; 好吧,基本上是进入“主”类和具有其他功能的mixin的,例如:

self文件:

import mymixin.py

class Main(object, MyMixin):

def func1(self, xxx):

...

self文件:

class MyMixin(object):

def func2(self: Main, xxx): #

...

现在,尽管这很好用,但是MyMixin.func2中的类型提示当然不起作用。 我无法导入main.py,因为会进行周期性导入,并且没有提示,我的编辑器(PyCharm)无法分辨self是什么。

使用Python 3.4,如果在那里有解决方案,则愿意升级到3.5。

有什么办法可以将我的班级分成两个文件并保留所有“连接”,以便我的IDE仍可以自动完成以及知道类型的所有其他优点。

5个解决方案

87 votes

恐怕通常没有一种非常优雅的方式来处理导入周期。 您的选择是重新设计代码以消除循环依赖性,或者如果不可行,请执行以下操作:

# some_file.py

from typing import TYPE_CHECKING

if TYPE_CHECKING:

from main import Main

class MyObject(object):

def func2(self, some_param: 'Main'):

...

deceze常量在运行时始终为Main,因此不会评估导入,但是mypy(和其他类型检查工具)将评估该块的内容。

我们还需要将deceze类型注释放入一个字符串中,因为Main符号在运行时不可用,因此可以有效地向前声明它。

如果您使用的是Python 3.7+,我们至少可以通过利用PEP 563跳过必须提供显式字符串注释的情况:

# some_file.py

from __future__ import annotations

from typing import TYPE_CHECKING

if TYPE_CHECKING:

from main import Main

class MyObject(object):

# Hooray, cleaner annotations!

def func2(self, some_param: Main):

...

deceze导入将使所有类型提示均为字符串,并跳过对它们的求值。 这可以使我们的代码更符合人体工程学。

综上所述,与mypy一起使用mixins可能需要比您现在拥有的结构更多的结构。 Mypy建议使用一种基本上是deceze所描述的方法-创建一个Main和MyMixin类都继承的ABC。 如果您最终需要做一些类似的事情以使Pycharm的检查器满意,我不会感到惊讶。

Michael0x2a answered 2019-11-10T04:02:51Z

9 votes

更大的问题是,您的类型一开始并不理智。 MyMixin做出了硬编码的假设,即将其混合到Main中,而可以将其混合到任何其他数量的类中,在这种情况下,它可能会损坏。 如果将mixin硬编码为混合到一个特定的类中,则不妨将方法直接写入该类中,而不用将它们分开。

要使用合理的输入正确执行此操作,应使用Python的说法对接口或抽象类进行编码MyMixin:

import abc

class MixinDependencyInterface(abc.ABC):

@abc.abstractmethod

def foo(self):

pass

class MyMixin:

def func2(self: MixinDependencyInterface, xxx):

self.foo() # ← mixin only depends on the interface

class Main(MixinDependencyInterface, MyMixin):

def foo(self):

print('bar')

deceze answered 2019-11-10T04:03:24Z

6 votes

对于仅在导入类以进行类型检查时陷入困境的人们:您可能希望使用前向引用(PEP 484-类型提示):

当类型提示包含尚未定义的名称时,该定义可以表示为字符串文字,稍后再解析。

所以代替:

class Tree:

def __init__(self, left: Tree, right: Tree):

self.left = left

self.right = right

你做:

class Tree:

def __init__(self, left: 'Tree', right: 'Tree'):

self.left = left

self.right = right

Tomasz Bartkowiak answered 2019-11-10T04:04:03Z

2 votes

事实证明,我最初的尝试也非常接近解决方案。 这是我目前正在使用的:

# main.py

import mymixin.py

class Main(object, MyMixin):

def func1(self, xxx):

...

# mymixin.py

if False:

from main import Main

class MyMixin(object):

def func2(self: 'Main', xxx): #

...

请注意,在if False语句中的import不会被导入(但IDE仍然知道),并且将Main类用作字符串,因为在运行时不知道。

velis answered 2019-11-10T04:04:35Z

-2 votes

我认为,完美的方法应该是将所有类和依赖项导入文件中(例如__init__.py),然后在所有其他文件中导入from __init__ import *。

在这种情况下

避免对这些文件和类的多次引用,并且

也只需在其他每个文件中添加一行

第三个是pycharm,它知道您可能使用的所有类。

AmirHossein answered 2019-11-10T04:05:27Z

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值