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

Iso*_*toR 6 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
Run Code Online (Sandbox Code Playgroud)

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

>>>import mod1

loading...
3
44
----------
Run Code Online (Sandbox Code Playgroud)

这里当我导入并运行该test函数时,它成功运行,虽然我甚至没有导入countCharscountLines,并且该from语句已经删除了mod2模块对象.

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

编辑:Thanx很多人回答:)

JBe*_*rdo 6

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

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

  • 整洁,我不知道`__globals__`. (3认同)

mgi*_*son 4

我认为你正在努力解决 python 处理的方式namespaces。当您键入时,from module import thing您正在将thingfrommodule引入当前的命名空间。因此,在您的示例中,mod1导入时,代码将按以下顺序求值:

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

现在对于 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
Run Code Online (Sandbox Code Playgroud)

所有这些之所以重要,是因为 python 可以让您准确选择要拉入命名空间的内容。例如,假设您有一个module1which 定义了 function cool_func。现在你正在编写另一个模块(module2),它使得 for也module2有一个函数cool_func。Python 允许您将它们分开。module3你可以这样做:

import module1
import module2
module1.cool_func()
module2.cool_func()
Run Code Online (Sandbox Code Playgroud)

或者,你可以这样做:

from module1 import cool_func
import module2 
cool_func() #module1
module2.cool_func()
Run Code Online (Sandbox Code Playgroud)

或者你可以这样做:

from module1 import cool_func as cool
from module2 import cool_func as cooler
cool()  #module1
cooler() #module2
Run Code Online (Sandbox Code Playgroud)

可能性还在继续......

希望我的观点很清楚。当您从模块导入对象时,您正在选择如何在当前命名空间中引用该对象。