导入位置

  • 本文关键字:位置 导入 python
  • 更新时间 :
  • 英文 :


我正在学习Python,今天在编写一些代码时,我试图决定在哪里放置import语句。

我可以将导入语句放在几乎任何看起来的地方,但是放置如何影响性能、命名空间以及我还不知道的任何其他内容?

官方的良好实践是将所有导入放在模块或脚本的开头,从标准 lib 模块/包开始,然后是第三部分,然后是特定于项目的,参见 http://www.python.org/dev/peps/pep-0008/#imports

实际上,有时你必须推迟导入到函数中,作为循环依赖的快速和肮脏的解决方法(解决循环依赖的正确方法是在另一个模块中提取相关部分,但对于某些框架,你可能不得不接受Q&D解决方法(。

恕我直言,出于"性能"原因推迟导入函数不是一个好主意,但有时您有时不得不打破规则。

导入模块实际上意味着:

search the module_or_package in `sys.modules`
if not found:
    search the module_or_package_source in `sys.path`
    if not found:
        raise an ImportError
    create a `module` instance from the module_or_package_source 
    # -> imply executing the top-level source code, which may raise anything
    store the `module` instance in `sys.modules`
bind the `module` name (or whatever name was imported from it) in the current namespace

wrt/"当前命名空间"是什么意思,它实际上是这样的:执行 import 语句的命名空间(模块的"全局"、函数的"本地"或class语句的主体(。下面是包含所有三个示例的简单脚本:

try:
    re
except NameError, e:
    print "name 're' is not yet defined in the module's namespace"
    print "module namespace : %s" % globals()
import re
print "name 're' is now defined in the module's namespace"
print "module namespace : %s" % globals()

def foo():
    try:
        os
    except NameError, e:
        print "name 'os' is not yet defined in the function's namespace"
        print "function namespace : %s" % locals()
        print "name 'os' is not defined in the module's namespace neither"
        print "module namespace : %s" % globals()
    import os
    print "name 'os' is now defined in the function's namespace"
    print "function namespace : %s" % locals()
    print "name 'os' is still not defined in the module's namespace"
    print "module namespace : %s" % globals()
foo()
print "After calling foo(), name 'os' is still not defined in the module's namespace"
print "module namespace : %s" % globals()
class Foo(object):
    try:
        os
    except NameError, e:
        print "name 'os' is not yet defined in the class namespace"
        print "but we cannot inspect this namespace now so you have to take me on words"
        print "but if you read the code you'll notice we can only get there if we have a NameError, so we have an indirect proof at least ;)"
        print "name 'os' is not defined in the module's namespace neither obvisouly"
        print "module namespace : %s" % globals()
    import os
    print "name 'os' is now defined in the class namespace"
    print "we still cannot inspect this namespace now but wait..."
    print "name 'os' is still not defined in the module's namespace neither"
    print "module namespace : %s" % globals()
print "class namespace is now accessible via Foo.__dict__"
print "Foo.__dict__ is %s" % (Foo.__dict__)
print "'os' is now an attribute of Foo - Foo.os = %s" % Foo.os
print "name 'os' is still not defined in the module's namespace"
print "module namespace : %s" % globals()

当你使用import时,你实际上执行它的(模块(代码。因此,如果您可以控制执行它(例如,如果某些条件有效,您只需要import(,那么将其放在您想要的任何位置。

if some_condition:
    import foo

如果您总是需要(无条件(它,请将其放在文件的顶部。

对于初学者,我建议始终将import语句放在文件的顶部。

导入通常放在文件的顶部,就像在其他编程语言中一样。将它们放在一起可以轻松一目了然地查看模块的依赖项。

但是,由于import执行模块的代码,因此可能是一项昂贵的操作,因此您有时会在函数中看到导入。NLTK是一个出了名的笨重的模块,所以当我使用它时,我有时会这样做

def _tokenize(text):
    import nltk
    return nltk.word_tokenize(text)
def process_some_text(text):
    if isinstance(text, basestring):
        text = _tokenize(text)
    # now do the actual processing

由于导入是缓存的,因此只有对_tokenize的第一次调用才会执行导入。这也具有使依赖项可选的效果,因为在调用方请求相关功能之前不会尝试import

首次导入模块时,Python 会搜索该模块,如果找到,它会创建一个模块对象。

根据模块的大小以及它在代码中的使用频率,您可能希望在文件顶部一次性导入它,或者您可能希望在满足特定条件时导入它。

系统内存始终受到限制 - 如果在极少数情况下很有可能满足模块的上述条件,则根据条件检查导入是有意义的。

如果您需要在代码中导入多个繁重的模块,这些模块将消耗大量内存,但在不同的地方需要它们,这将特别有用。所以与其像那样做

import module1 
import module2
def foo1()
    module1.function()
def foo2()
    module2.function()
foo1()
foo2()

尝试类似的东西

def foo1()
    import module1 
    module1.function()
def foo2()
    import module2
    module2.function()
foo1()
foo2()

如果 python 模块足够简单,那么将它们包含在文件顶部是有意义的 - 这样,正在阅读代码的其他人也可以事先了解您当前代码使用的所有模块。

您可以在使用它之前将其放在文件中的任何位置。 您通常不应该将其放在循环中(因为它不会完全按照您的期望执行(,但可以将其放在条件中。 执行导入的模块初始化代码时,只有在知道需要时才加载它,可以节省一些时间。

你可以把它放在函数中,但如果在函数中,那么它只会在该函数的范围内。

>>> def f1():
...    import sys
...    print sys.version
...
>>> def f2():
...    print sys.version
...
>>> f2()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in f2
NameError: global name 'sys' is not defined
>>> f1()
2.5.4 (r254:67916, Dec 23 2008, 15:10:54) [MSC v.1310 32 bit (Intel)]
>>> f2()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in f2
NameError: global name 'sys' is not defined
>>>

要遵循的一个很好的约定是将其放在文件的顶部,以便始终可用且易于查找。

您可能还会发现,特别是对于测试包组件,您可能需要在某些导入之前修改 sys.path,以便尽早导入。

我个人认为有用的约定是先导入所有系统,然后导入项目包,然后导入本地导入,并在它们之间进行适当的注释。

如果您import模块名称from模块import子模块import模块as别名,则导入顺序应该没有重大区别,但是如果您from模块import *那么所有赌注都是错误的,因为各种模块可以定义相同的名称,最后一个将是你得到的 - 这只是不鼓励的原因之一。

相关内容

  • 没有找到相关文章

最新更新