`从。。。导入“vs”导入`

2024-04-23 18:28:33 发布

您现在位置:Python中文网/ 问答频道 /正文

我想知道代码片段之间是否有区别

from urllib import request

还有碎片

import urllib.request

或者它们是可以互换的。如果它们是可互换的,哪种是“标准/首选”语法(如果有)?

谢谢!


Tags: 代码fromimport标准request语法urllib碎片
3条回答

这是有区别的。在某些情况下,其中一个可以工作,另一个不行。下面是一个例子:假设我们有以下结构:

foo.py
mylib\
    a.py
    b.py

现在,我要将b.py导入a.py。我想把a.py导入foo。我该怎么做?我在a中写了两个语句:

import b

foo.py中,我写:

import mylib.a

好吧,这将在尝试运行foo.py时生成ImportError。解释器会抱怨a.pyimport b)中的import语句说没有模块b。那么如何解决这个问题呢?在这种情况下,将a中的import语句更改为import mylib.b 不会工作,因为ab都在mylib中。这里的解决方案(或至少一个解决方案)是使用绝对导入:

from mylib import b

来源:Python: importing a module that imports a module

这取决于引用导入时要如何访问导入。

from urllib import request
# access request directly.
mine = request()

import urllib.request
# used as urllib.request
mine = urllib.request()

在导入时,为了简单或避免掩蔽内置组件,您还可以自己对事物进行别名:

from os import open as open_
# lets you use os.open without destroying the 
# built in open() which returns file handles.

很多人已经解释过importfrom的关系,所以我想尝试在幕后解释一下,实际的区别在哪里。

首先,让我解释一下基本导入语句的作用。

import X

Imports the module X, and creates a reference to that module in the current namespace. Then you need to define completed module path to access a particular attribute or method from inside the module (e.g.: X.name or X.attribute)

from X import *

Imports the module X, and creates references to all public objects defined by that module in the current namespace (that is, everything that doesn’t have a name starting with _) or whatever name you mentioned.

Or, in other words, after you've run this statement, you can simply use a plain (unqualified) name to refer to things defined in module X. But X itself is not defined, so X.name doesn't work. And if name was already defined, it is replaced by the new version. And if name in X is changed to point to some other object, your module won’t notice.

This makes all names from the module available in the local namespace.

现在让我们看看当我们做import X.Y时会发生什么:

>>> import sys
>>> import os.path

用名称osos.path检查sys.modules

>>> sys.modules['os']
<module 'os' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc'>
>>> sys.modules['os.path']
<module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>

检查名称为oslocals()的名称空间dict:

 >>> globals()['os']
<module 'os' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc'>
>>> locals()['os']
<module 'os' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc'>
>>> globals()['os.path']
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'os.path'
>>>    

从上面的例子中,我们发现只有os被添加到本地和全局名称空间中。 因此,我们应该能够使用os

 >>> os
 <module 'os' from     
  '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc'>
 >>> os.path
 <module 'posixpath' from      
 '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
 >>>

…但不是path

>>> path
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'path' is not defined 
>>>

一旦从locals()命名空间中删除os,就无法访问osos.path,即使它们确实存在于sys.modules

>>> del locals()['os']
>>> os
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'os' is not defined
>>> os.path
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'os' is not defined
>>>

现在让我们看看from

from

>>> import sys
>>> from os import path

用名称osos.path检查sys.modules

>>> sys.modules['os']
<module 'os' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc'>
>>> sys.modules['os.path']
<module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>

所以sys.modules看起来和我们使用import name导入时一样。

好吧。让我们检查一下locals()globals()命名空间dict是什么样子的:

>>> globals()['path']
<module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
>>> locals()['path']
<module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
>>> globals()['os']
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'os'
>>>

您可以使用path访问,但不能使用os.path

>>> path
<module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
>>> os.path
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'os' is not defined
>>>

让我们从locals()中删除“path”:

>>> del locals()['path']
>>> path
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'path' is not defined
>>>

最后一个使用别名的示例:

>>> from os import path as HELL_BOY
>>> locals()['HELL_BOY']
<module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
>>> globals()['HELL_BOY']
<module 'posixpath' from /System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
>>>

没有定义路径:

>>> globals()['path']
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
KeyError: 'path'
>>>

使用from的一个陷阱

当您从两个不同的模块导入相同的name时:

>>> import sys
>>> from os import stat
>>> locals()['stat']
<built-in function stat>
>>>
>>> stat
<built-in function stat>

再次从shutil导入stat:

>>>
>>> from shutil import stat
>>> locals()['stat']
<module 'stat' from 
'/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/stat.pyc'>
>>> stat
<module 'stat' from 
'/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/stat.pyc'>
>>>

最后一次导入将获胜

相关问题 更多 >