当前位置:  开发笔记 > 编程语言 > 正文

在导入的__init__.py中,导入的行为会有所不同

如何解决《在导入的__init__.py中,导入的行为会有所不同》经验,为你挑选了1个好方法。

__init__.py运行文件时,导入时的行为似乎与导入时的行为不同.

如果我们有以下文件:

run.py:

import test

test/b.py:

class B(object):
    pass

test/__init__.py:

from b import B
print B
print b

如果我们运行,__init__.py我们会得到一个错误:

% python test/__init__.py


Traceback (most recent call last):
  File "test/__init__.py", line 6, in 
  print b
NameError: name 'b' is not defined

但如果我们run.py这样做,那么我们不会:

% python run.py 


我希望这种行为是一样的.为什么这样做?

这只有在我们这样做的情况下才有效__init__.py.要是我们:

mv __init__.py a.py
touch __init__.py

并使run.py:

import test.a

然后我们得到了错误.



1> Andrea Corbe..:

情况如下:你有一个脚本(run.py),一个包test及其子模块test.b.

每当您在Python中导入子模块时,该子模块的名称都会自动存储到父包中.因此,当您执行import collections.abc(或from collections.abc import Iterable类似)时,包会collections自动获取该属性abc.

这就是这里发生的事情.当你这样做时:

from b import B

名称b是自动加载的test,因为btest包的子模块.

即使您没有import b明确地执行,每当您导入该模块时,名称都会被放入test.因为b是子模块test,它属于test.


侧节点:您的代码不适用于Python 3,因为相对导入已被删除.要使代码与Python 3一起使用,您必须编写:

from test.b import B

这种语法完全相同from b import B,但更加明确,应该可以帮助您了解正在发生的事情.


参考:在Python的参考文档也解释了这种行为,并包含一个有用的例子,非常类似于这种情况(所不同的是仅仅是一个绝对导入使用,而不是相对进口).

当使用任何机制(例如importlibAPI,importimport-from语句或内置__import__())加载子模块时,绑定将放置在父模块的命名空间中,并放置到子模块对象中.例如,如果包spam具有子模块foo,则在导入之后spam.foo,spam将具有foo绑定到子模块的属性.

假设您有以下目录结构:

spam/
    __init__.py
    foo.py
    bar.py

spam/__init__.py在其中包含以下内容:

from .foo import Foo
from .bar import Bar

然后执行以下把将名称绑定到foobar所述在spam模块:

>>> import spam
>>> spam.foo

>>> spam.bar

鉴于Python熟悉的名称绑定规则,这似乎令人惊讶,但它实际上是导入系统的基本功能.不变控股是,如果你有sys.modules['spam']sys.modules['spam.foo'](可能也会上述进口后),后者必须表现为foo前者的属性.

推荐阅读
农大军乐团_697
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有