关于Python中的导入的一些混淆

时间:2012-08-14 18:03:30

标签: python import module

我是Python的新手,并且有一段时间以来一直困扰着我的东西。我在Mark Lutz的“学习Python”中读到,当我们使用from语句导入模块中存在的名称时,它首先导入模块,然后为其指定一个新名称(即函数的名称) ,类等存在于导入的模块中),然后使用del语句删除模块对象。但是,如果我尝试使用引用自身未导入的导入模块中的名称的from导入名称会发生​​什么?请考虑以下示例,其中有两个模块mod1.pymod2.py

#mod1.py
from mod2 import test
test('mod1.py')        

#mod2.py
def countLines(name):
    print len(open(name).readlines())

def countChars(name):
    print len(open(name).read())

def test(name):
    print 'loading...'
    countLines(name)
    countChars(name)
    print '-'*10

现在看看当我运行或导入mod1时会发生什么:

>>>import mod1

loading...
3
44
----------

在我导入并运行test函数时,虽然我甚至没有导入countCharscountLines,但from语句已被删除,但它已成功运行mod2模块对象。

所以我基本上需要知道为什么这个代码工作,即使考虑到我提到它不应该的问题。

编辑:Thanx很多人回答:)

6 个答案:

答案 0 :(得分:6)

每个函数都有一个__globals__属性,该属性包含搜索全局变量和函数的环境的引用。

然后test函数链接到mod2的全局变量。因此,当它调用countLines时,即使您在导入函数的模块中编写了一个具有相同名称的新函数,解释器也总能找到正确的函数。

答案 1 :(得分:4)

我认为你正在与python处理namespaces的方式搏斗。当您键入from module import thing时,您将thingmodule带入当前命名空间。因此,在您的示例中,导入mod1时,将按以下顺序评估代码:

from mod2 import test #Import mod2, bring test function into current module namespace
test("mod1.py")  #run the test function (defined in mod2)

现在对于mod2:

#create a new function named 'test' in the current (mod2) namespace 
#the first time this module is imported.  Note that this function has
#access to the entire namespace where it is defined (mod2).
def test(name):  
    print 'loading...'
    countLines(name)
    countChars(name)
    print '-'*10

所有这一切都很重要的原因是因为python允许您准确选择要引入命名空间的内容。例如,假设您有一个定义函数module1的{​​{1}}。现在您正在编写另一个模块(cool_func),因为module2也有一个函数module2。 Python允许您将它们分开。在cool_func你可以做到:

module3

或者,你可以这样做:

import module1
import module2
module1.cool_func()
module2.cool_func()

或者你可以这样做:

from module1 import cool_func
import module2 
cool_func() #module1
module2.cool_func()

可能性继续......

希望我的观点很明确。从模块导入对象时,您将选择在当前命名空间中引用该对象的方式。

答案 2 :(得分:3)

其他答案比这个答案更明确,但如果您运行以下内容,则可以看到countCharscountLines实际上都是test.__globals__中定义的:

from pprint import pprint
from mod2 import test

pprint(test.__globals___)
test('mod1')

您可以看到导入test带来mod2中定义的其他全局变量,让您运行该函数而不必担心必须导入所需的所有内容。

答案 3 :(得分:1)

每个模块都有自己的范围。在mod1内,您无法使用名称countLinescountChars(或mod2)。

mod2本身不会受到影响,至少它是如何在其他地方导入的;其中定义的所有名称都可在模块中使用。

如果您引用的网页确实表示使用del语句删除了模块对象,那就错了。 del仅删除名称,不会删除对象。

答案 4 :(得分:1)

import语句将整个模块加载到内存中,这就是test()函数成功运行的原因。

但是,当您使用from语句时,这就是您无法直接使用countLinescountCharstest肯定会调用它们的原因。

from语句基本上加载整个模块,并将导入的函数,变量等设置为全局命名空间。

例如。

>>> from math import sin
>>> sin(90)               #now sin() is a global variable in the module and can be accesed directly
0.89399666360055785
>>> math
Traceback (most recent call last):
  File "<pyshell#2>", line 1, in <module>
    math
NameError: name 'math' is not defined
>>> vars()  #shows the current namespace, and there's sin() in it
{'__builtins__': <module '__builtin__' (built-in)>, '__file__': '/usr/bin/idle', '__package__': None, '__name__': '__main__', 'main': <function main at 0xb6ac702c>, 'sin': <built-in function sin>, '__doc__': None}

考虑一个简单的文件,file.py:

def f1():
   print 2+2

def f2():
   f1()

仅导入f2:

>>> from file import f2
>>> f2()
4

虽然我只导入了f2()而不是f1()但它成功运行了f1()因为模块已加载到内存中但我们只能访问f2(),但是{{1可以访问模块的其他部分。

答案 5 :(得分:1)

来自A GUIDE TO PYTHON NAMESPACES

  

尽管模块有自己的全局命名空间,但这并不意味着可以从模块中的任何位置使用所有名称。范围是指程序的一个区域,在该区域中可以访问名称空间而无需前缀。范围对于它们在模块中提供的隔离很重要。在任何时候都有许多作用域:你所在的当前函数的范围,模块的范围,然后是Python内置函数的作用域。这种范围嵌套意味着一个函数无法访问另一个函数内的名称。

     

还会在内部搜索名称空间的名称。这意味着如果在模块的全局命名空间中声明了某个名称,则可以在函数内重用该名称,同时确定任何其他函数将获取全局名称。当然,您可以通过在名称前加上'global'关键字来强制该函数使用全局名称。但是如果你需要使用它,那么你可能最好使用类和对象。