2009-11-09 74 views
19

在导入代码的各种方式中,与其他方法相比,有哪些方法可以使用?这在短期 链接http://effbot.org/zone/import-confusion.htm指出Python(和Django)最佳导入实践

from foo.bar import MyClass 

不导入正常情况下,或者除非你知道自己在做什么MyClass的首选方式。 (更确切地说,一个更好的办法想:

import foo.bar as foobaralias 

,然后在代码中,访问MyClass的使用

foobaralias.MyClass 

总之,似乎上述引用链接说这是通常更好地导入从模块,而不是只是部分模块的一切。

但是,我链接的那篇文章真的很老。

我也听说,至少在Django项目的上下文中,反而只导入要使用的类,而不是整个模块更好。据说这种形式有助于避免循环导入错误,或者至少使django导入系统更脆弱。有人指出,Django自己的代码似乎更喜欢“从x导入y”到“导入x”。

假设我正在处理的项目没有使用__init__.py的任何特殊功能...(我们的所有__init__.py文件都是空的),我应该使用哪种导入方法,为什么?

回答

5

对于我来说,这是依赖于局势。如果它是一个唯一命名的方法/类(即不是process()或类似的东西),并且您打算使用它,那么保存输入并只需执行from foo import MyClass

如果要从一个模块导入多个东西,最好只导入模块,并执行module.bar, module.foo, module.baz等,以保持名称空间的清洁。

您也说

有人说,这种形式有助于避免循环导入错误或至少使Django的导入系统不那么脆弱。有人指出,Django自己的代码似乎更喜欢“从x导入y”到“导入x”。

我不明白这种方式或其他方式如何防止循环导入。原因是,即使在做from x import y,导入所有x。只有y被带入当前命名空间,但整个模块x都被处理。试试下面这个例子:

在test.py,把下面的:

def a(): 
    print "a" 

print "hi" 

def b(): 
    print "b" 

print "bye" 

然后在 'runme.py',就把:

from test import b 

b() 

然后就去做python runme.py

您将看到以下输出:

hi 
bye 
b 

因此,即使您只导入了b

2

后者的优点是MyClass的起源更加明确。前者将MyClass放入当前名称空间,以便代码可以仅使用MyClass不合格。所以对于读MyClass定义的代码的人来说,这并不那么明显。

13

首先,主要的进口规则:永远不会使用from foo import *

本文正在讨论周期性进口问题,该问题目前仍存在于结构不良的代码中。我不喜欢周期性进口;他们的存在是一个很强的信号,表明某些模块做得太多,需要分解。如果出于任何原因,您需要使用无法重新安排的周期性进口代码,import foo是唯一的选择。

对于大多数情况下,import foofrom foo import MyClass之间没有太大差别。我倾向于第二种,因为没有涉及到更少的输入,但就是为什么我会用第几个原因:

  • 模块和类/值有不同的名称。读者可能很难记住特定导入来自哪里,导入的值的名称与模块无关。

    • 好:import myapp.utils as utils; utils.frobnicate()
    • 好:import myapp.utils as U; U.frobnicate()
    • 坏:from myapp.utils import frobnicate
  • 你从一个模块中导入了大量的值。保存你的手指和读者的眼睛。

    • 坏:from myapp.utils import frobnicate, foo, bar, baz, MyClass, SomeOtherClass, # yada yada
+0

因此,test.py中的所有内容都已运行。对此的特定异常可能在您导入实现模型(表示数据库表)的类的Django中。在这种情况下,最好说“从django.contrib.auth导入用户”。但正如我所说,这是一个特定于特定环境的惯例。 – 2009-11-10 03:13:05

+2

从myapp导入utils怎么样; utils.frobnicate()'? – Joschua 2010-09-16 09:59:14

+1

Joschua:这很好,因为任何人都可以看到'frobnicate'从哪里进口。 – 2010-09-16 17:23:23