2

我需要澄清在同一个命名空间中共存时如何处理模块和类级别的导入。请参阅以下示例:

作品:

import datetime
print datetime.datetime.utcnow()

失败:

from datetime import datetime
print datetime.datetime.utcnow()

错误:AttributeError:类型对象“datetime.datetime”没有属性“datetime”

作品:

from datetime import datetime # Is this ignored?
import datetime
print datetime.datetime.utcnow()

第三个例子到底发生了什么?第二个模块导入是否替换了特定于类的第一个导入?这是否意味着模块和类级别的导入不应该混合在同一个命名空间中?

4

5 回答 5

6

没有优先级是这样的。结果由import执行语句的顺序决定,如下所示。

如果您尝试将多个调用的内容X导入您的命名空间,则每个导入都会重新绑定X到它正在导入的任何内容。

因此,最后将是最后一个导入,就所涉及的名称X而言将有效。

这正是您的第三个示例中发生的情况:

from datetime import datetime # This isn't ignored, but the name is immediately rebound
                              # by the next line
import datetime               # Rebinds the name
于 2012-12-06T16:43:15.440 回答
2

一些支持 python 的 IDE 会给您解释,但是是的,您正在重新定义(覆盖、替换)第三个示例中的导入。文件中的每个名称都是不同的。如果您需要访问共享名称的模块和类,您需要使用类似from datetime import datetime as dt.

于 2012-12-06T16:43:29.647 回答
1

导入实际上只是一个分配:它在您当前的命名空间中设置一个名称。因此,在第三种情况下,您将名称设置datetime为与 datetime 类相同,然后立即将其重新分配给 datetime 模块。

于 2012-12-06T16:52:16.840 回答
0

您的第一个示例导入datetime模块并datetime在表示它的本地命名空间中提供一个标签,然后调用属于该模块utcnow()的对象的方法。第二个将对象(不是模块)添加到带有标签的本地命名空间,但对象没有属性,所以你得到了异常。第三个示例将对象分配给命名空间中该名称的标签,然后将标签重新分配给模块。因此,忽略与这个问题无关的机制(基本上,如果模块尚不存在,则添加模块),您所拥有的相当于:datetimedatetimedatetime.datetimedatetimedatetimedatetimedatetime.datetimedatetimeimportsys.modules

datetime = sys.modules['datetime']
datetime.datetime.utcnow()

然后

datetime = sys.modules['datetime'].datetime
datetime.datetime.utcnow()

然后

datetime = sys.modules['datetime'].datetime
datetime = sys.modules['datetime']
datetime.datetime.utcnow()
于 2012-12-06T16:45:07.393 回答
0

没有理由这样做:

from datetime import datetime
print datetime.datetime.utcnow()

另一方面,此代码将完全按照您的要求执行:

from datetime import datetime
print datetime.utcnow()
于 2012-12-06T16:46:20.323 回答