导入语句如何修改模块的符号表?

时间:2019-06-13 10:42:06

标签: python

我有以下模块:

#include <iostream>
#include <vector>

using namespace std;

int main(){

int a;
int b;
int c;
int d;
int result;


while(cin >> a >> b >> c){

    result = 0;

}
vector <int > v;
while(cin >> d);{
    v.push_back(d);

    }
    for( int i = 0; i < v.size();i++);
        cout << v[i] << endl;
    if (a>=b) cout << 0 << endl;

    else {

    }           
}

foo/ __init__.py random.py 只是一个空文件,random.py包含以下内容:

__init__.py

当我用import random def print_random(): import foo.random print(random.random()) 调用上述函数时,我得到了python -c 'import foo; foo.print_random()'

似乎AttributeError: module 'foo.random' has no attribute 'random'中的import语句已将对内置模块的引用替换为对print_random()的引用。谁能向我解释为什么它没有在上述表中添加新记录?我在哪里可以了解更多信息?有避免这种情况的推荐做法吗?

更新#1

我在Python 2.7和Python 3.5中都遇到了相同的错误。我注意到的唯一区别是,与Python 2相比,措词略有不同:foo.random

AttributeError: 'module' object has no attribute 'random'中的

sys.modules['random']指的是内置随机模块,而print_random()指的是globals()['random']

foo/random.py不必位于import foo.random中。可以从那里删除它,并将其添加到运行脚本的命令中(例如python -c'import foo; import foo.random; foo.print_random()'),这将产生相同的结果。

1 个答案:

答案 0 :(得分:2)

这里有两种机制:

一方面,当执行import foo.random语句时,我们通常希望名称foo将绑定在本地上下文中,并且foo.random将作为成员可用导入语句的docs.

foo

另一方面,根据子模块doc,“使用任何一种机制加载子模块时,都会在父模块的命名空间中放置与子模块对象的绑定”。

__init__.py文件的特殊情况下,这意味着foo.random可以作为名称random和绑定到{的对象的random成员使用{1}},因为在foo文件中,我们直接在父模块的上下文中工作(即,我们在__init__.py上下文中工作,而不是在foo上下文中工作)。

最好的解决方案是,如果可以避免的话,不要在foo.__init__包中编写代码,而只是使用它公开名称,初始化记录器等。始终为以下模块创建包是一种很好的做法:尽管不能解决此问题,但相对于父包而言,它具有更好的表达能力。

最后,如果您想在具有以上内容的__init__函数的同时公开foo.random包,我建议采用以下布局:

foo.print_random

foo / __ init __。py

foo/
  __init__.py
  print_random.py
  random/
    __init__.py

foo / print_random.py

from foo.print_random import print_random