我试图把我庞大的班级一分为二;好的,基本上分为“main”类和带有附加函数的mixin,如下所示:
main。py
文件:
import mymixin.py
class Main(object, MyMixin):
def func1(self, xxx):
...
mymixin。py
文件:
class MyMixin(object):
def func2(self: Main, xxx): # <--- note the type hint
...
现在,虽然这很好,但是MyMixin中的类型提示。func2当然不能工作。我无法导入
main。py
,因为我会得到一个循环导入,并且没有提示,我的编辑器(PyCharm)无法分辨什么是self
。
我使用的是Python3.4,但如果有解决方案,我愿意使用3.5。
有没有什么方法可以把我的类分成两个文件,并保留所有的“连接”,这样我的IDE仍然可以为我提供自动完成和所有其他知道类型的好东西?
更大的问题是你的类型一开始就不健全MyMixin
硬编码假设它将混合到Main
中,而它可以混合到任何数量的其他类中,在这种情况下,它可能会中断。如果您的mixin被硬编码为混合到一个特定的类中,那么您也可以将方法直接写入该类中,而不是将它们分离出来。
为了正确地使用正常的类型来完成这一操作,应该针对接口或Python术语中的抽象类进行编码:
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')
对于仅为类型检查而导入类时遇到循环导入困难的用户:您可能希望使用正向引用(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
恐怕没有一个非常优雅的方法来处理一般的导入周期。您可以选择重新设计代码以删除循环依赖关系,或者如果不可行,则执行以下操作:
# some_file.py
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from main import Main
class MyObject(object):
def func2(self, some_param: 'Main'):
...
TYPE_CHECKING
常量在运行时总是False
,因此导入不会被计算,但是mypy(和其他类型检查工具)将计算该块的内容。
我们还需要将Main
类型注释变成一个字符串,有效地向前声明它,因为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):
...
来自未来导入注释的导入将使所有类型提示成为字符串,并跳过对它们的求值。这有助于使我们的代码稍微更符合人体工程学。
尽管如此,与mypy一起使用混合可能需要比您目前拥有的更多的结构。Mypy推荐了一种基本上就是
deceze
所描述的方法创建一个ABC,您的Main
和MyMixin
类都继承了这个ABC。如果你最终需要做类似的事情来让皮魅力的支票员开心,我不会感到惊讶。
问题内容: 我正试图将我的大班分成两部分;好吧,基本上是进入“主”类和具有其他功能的mixin的,就像这样: 文件: 文件: 现在,尽管这很好,但类型提示当然不起作用。我无法导入,因为会进行周期性导入,并且没有提示,我的编辑器(PyCharm)无法分辨出什么。 我正在使用Python 3.4,如果那里有解决方案,我愿意移至3.5。 有什么办法可以将我的班级分成两个文件并保留所有“连接”,以便我的I
我有Python类,它们有彼此作为属性的实例 如果这些类是在同一个文件中定义的,那么这很好,但是在我的例子中,它们都非常大,我希望将它们移动到不同的文件中。但是,如果我这样做,我必须将导入和导入,这将导致循环导入错误。有人知道我可以使用哪种模式将和放在不同的文件中,保持类型暗示,并遇到循环导入错误吗?
问题内容: 如果两个模块相互导入会怎样? 为了概括这个问题,Python中的循环导入又如何呢? 问题答案: 导入确实非常简单。只要记住以下几点: 和是可执行语句。它们在运行的程序到达该行时执行。 如果模块不在中,则导入将在中创建新的模块条目,然后在模块中执行代码。在执行完成之前,它不会将控制权返回给调用模块。 如果中确实存在一个模块,则无论导入是否完成执行,导入都会简单地返回该模块。这就是循环导入
问题内容: 所以我得到这个错误 并且你可以看到我进一步使用了相同的import语句,并且可以正常工作吗?关于循环导入是否有一些不成文的规定?如何在调用堆栈的更下方使用同一类? 问题答案: 我认为jpmc26的答案虽然绝非错误,但在循环进口上却过于严格。如果正确设置它们,它们可以正常工作。 最简单的方法是使用语法,而不是。前者几乎总是可以工作,即使包括在内也能使我们重新获得利益。后者只有在中已经定义
问题内容: 假设我具有以下目录结构: 在软件包的中,将导入软件包。但是进口。 程序失败,表示尝试导入b时不存在。(它实际上不存在,因为我们正在导入它。)`c_file.pya.b.d `如何解决这个问题? 问题答案: 如果a取决于c,而c取决于a,那么它们实际上不是同一单位吗? 您应该真正检查一下为什么将a和c拆分为两个包,因为您应该将一些代码拆分为另一个包(以使它们都依赖于该新包,而不是彼此依赖
问题内容: 我真的没有得到这个,所以如果有人可以解释它是如何工作的,我将非常感激。我有两个应用程序,“帐户”和“主题” …这是我的设置列表: 在帐户中,我正在尝试执行以下操作: 在我的主题模型中: Django踢出以下错误: 这是某种循环进口问题吗?我尝试使用一个懒惰的引用,但这似乎也不起作用! 问题答案: 删除的导入,并将模型名称用作字符串。