所有动态语言都有循环导入问题吗?
对于以下 Python 代码:
first.py
# first.py
from second import Second
class First:
def __init__(self):
print 'Second'
second.py
# second.py
from first import First
class Second:
def __init__(self):
print 'Second'
创建文件并从 shell 运行以下命令后:
python first.py
我收到错误: ImportError: 无法导入name Second
像Ruby这样的其他动态语言有这种问题吗?我问的原因是因为我在 Django 项目中遇到了这个问题,其中两个模型相互依赖。我知道可能的解决方案是重新设计项目或按需导入。我只是想知道其他动态语言的开发人员是否遇到过这个问题。
For the following Python code:
first.py
# first.py
from second import Second
class First:
def __init__(self):
print 'Second'
second.py
# second.py
from first import First
class Second:
def __init__(self):
print 'Second'
After creating the files and running the following from the shell:
python first.py
I get the error: ImportError: cannot import name Second
Do other dynamic languages like Ruby have this kind of issue? The reason I'm asking is because I'm encountering this issue in a Django project where 2 models depend on each other. I know that the possible solutions are re-designing the project or import on demand. I just want to know if devs in other dynamic languages have experienced this issue.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
请注意,如果您只是将导入移动到模块的末尾,循环导入将按预期工作。像这样:
first.py
second.py
Fredrik Lundh 的导入参考值得一读。不过,正如其他人所建议的那样,您最好重新调整代码以避免完全循环导入。
Note that if you just move your imports to the end of your module, circular imports will work as expected. Like so:
first.py
second.py
Fredrik Lundh's import reference is worth a read. As others have advised, though, you're best off rejiggering your code to avoid circular imports entirely.
Python 在某种程度上可以处理循环导入。在无法理解的情况下,解决方案在另一种语言中可能仍然没有意义。大多数问题可以通过使用
import first
并稍后引用first.First
而不是from first import First
来解决。如果您可以将共享代码移至其自己的模块或以某种方式重构循环导入的需要,那就更好了。 循环导入总是表明存在设计问题。
Python can handle circular imports to some extent. In cases where no sense can be made, the solution would probably still not make sense in another language. Most of the problems can be cleared up by using
import first
and later referring tofirst.First
instead offrom first import First
.It would be better if you could move shared code off to its own module or somehow refactor out the need for a circular import. Circular imports always indicate a design problem.
递归定义不只是动态语言的问题。这在静态类型语言中也经常是一个问题。它可能会显示为编译错误,因为其中一种类型将在定义之前使用。
在某些语言中,解决方案是使用前向声明。其他语言通过一次编译多个文件来解决这一问题。
在 Python 中,您可以通过将导入从顶层移动到需要它们的函数中来解决问题。另外,循环引用实际上并不是一个错误,所以如果你小心的话,无论如何你都可以让它工作。
Recursive definitions are not a problem restricted to dynamic languages. It's also often an issue in statically types languages. It might show up as a compile error because one of the types will be used before it is defined.
In some languages the solution is to use forward declarations. Other languages solve the problem by compiling more than one file at once.
In Python you can solve the problem by moving the imports from the top level into the functions where they are needed. Also, a circular reference isn't actually an error, so if you are careful, you can make it work anyway.
所有其他海报都是正确的,循环导入是一个严重的问题,您应该从结构上解决。
然而,特别是对于 Python/Django 模型,您可以使用字符串名称来设置外键,以避免这些循环依赖问题——
数据库表中的循环引用不一定是坏事(但并不总是好事); Django 允许使用字符串定义键,以在必要时提供帮助。如果您实际上需要在彼此内部实例化这两个类,则会遇到更大的问题。
All other posters are correct that circular imports are a serious issue that you should fix, structurally.
However, specificly with Python/Django models, you can use string names to setup foreign keys to avoid these circular dependency issues --
Circular references in DB tables aren't necessarily a bad thing (but aren't always good); Django allows for definition of keys with a string to help in situations where it's necessary. If you actually need to instantiate the two classes inside one another, you've got bigger problems.
从逻辑上讲,这是一个悖论。从代码的角度来说,这是先有鸡还是先有蛋的问题。其中一个必须是第一位的。正如其他人所建议的,请回到绘图板,从长远来看,你会得到更好的结果。语言阻止你做这些事情是有原因的!
Logically this is a paradox. It's the chicken and egg issue in code form. One of them has to come first. As suggested by the others, please go back to the drawing board and you'll be better off for it in the long run. Languages prevent you from doing this stuff for a reason!