误解Python导入

时间:2013-09-11 03:31:13

标签: python import

我的编程方式经常出现问题,我需要帮助重组我的工作方式。

警告:这是一个很长的问题。我希望尽可能多地包含有关错误性质的信息,以消除可能的错误原因。

TL; DR版本: import / include命令不允许我的主文件查看其他文件中定义的函数。如何改进我的编程风格以防止以后出现这种情况?

长版本:我将以Python 2.7为例。假设我有一个文件main.py和另一个文件foo.pymain.py包含我的所有主要代码,foo.py有一个包含main.py中使用的数据的类。我所做的是在类定义之后,在同一个文件foo.py中定义类的对象。我想如果我只是在那里实例化类,我可以简单地将该文件导入到需要它的任何其他文件中,并且该对象已经存在以便立即使用。在某些时候实例化类并且担心在类的实例化之前是否需要它在实际定义之前是否需要它之前没有任何麻烦。

问题是这通常有效,直到我用另一个文件中定义的另一个类来做。解释器找不到第二个类的对象,即使我在main.py中导入它一次(因此这似乎不是源于多个导入的重复对象的问题)。所以,从本质上讲,main.py可以看到foo.py的类对象,但不是bar.py的对象。

我通常设置一个项目,以便我有一个主文件,以及定义数据以及该数据的使用和处理的其他文件。主文件调用一个函数或方法,通过调用整个程序中的其他函数和方法来实现滚动。我只导入我正在调用其方法的类的数据,并在具有主文件中使用的数据的文件中,导入特定文件所需的所有其他内容。如果我要制作一个节省内存的程序,这对我来说似乎是合乎逻辑的,但是我做事的方式显然有问题,因为它似乎永远不会适用于更大的程序。

以下是代码中的一个简单示例(a。我如何设置文件层次结构,(b。我如何设置导入,以及(c。我得到的错误类型示例:

main.py:

import foo
import bar

print foo.bar
print bat.bar

foo.py:

class Foo:
  def __init__(self):
    bar = 5

foo = Foo()

bar.py:

class Bar:
  def __init__(self):
    bar = "Hello"

bat = Bar()

这是我运行此程序时遇到的错误:

Traceback (most recent call last):
  File "C:\Users\User\Desktop\main.py", line 4, in <module>
    print foo.bar
AttributeError: 'module' object has no attribute 'bar'

当我将main.py更改为:

from foo import *
from bar import *

print foo.bar
print bat.bar

它得到了一个不同的错误:

Traceback (most recent call last):
  File "C:\Users\User\Desktop\main.py", line 4, in <module>
    print foo.bar
AttributeError: Foo instance has no attribute 'bar'

我误解了如何使用进口或什么?因为如果我退后一步这样做main.py

from foo import *
from bar import *

foo = Foo()
bat = Bar()

print foo.bar
print bat.bar

在注释掉其他文件中的类的实例化时,我得到了同样的错误:Foo instance has no attribute 'bar'

为什么会这样?

这不仅仅发生在Python上,它也发生在C ++上,所以这就是为什么我认为这可能是我的编程风格,这是一个问题,而不是语法上的任何东西。

1 个答案:

答案 0 :(得分:3)

import X在当前命名空间中创建一个X对象,其中包含该模块中定义的名称。这只会在命名空间中添加单个名称。所以,在你的第一个例子中,

import foo
import bar

使foo成为一个模块对象,其中包含类Foo(可以foo.Foo访问)和对象foo(可以foo.foo访问);类似地,bar具有类bar.Bar和对象bar.bat。值得注意的是,由于模块bar的顶层没有名为foo的变量,foo.bar不存在。

from X import YY中与模块X匹配的所有内容直接导入您的命名空间。这可能会在您当前的命名空间中创建一堆名称。所以,

from foo import *

创建名称Foo(引用类)和foo(引用Foo的实例)。因此,在后一种情况下,foo将引用类Foo的实例,那么为什么foo.bar不起作用?

嗯,你实际上没有定义foo.bar。代码

def __init__(self):
    bar = 5

定义名为bar局部变量,其值为5。它不会向类实例保存任何内容!你必须写

def __init__(self):
    self.bar = 5

完全有这项工作。

如果您遇到与C ++类似的问题,我建议放慢速度,一次只关注一种语言。没有充分的理由尝试同时学习,因为它会让你长期迷惑。在尝试学习另一种语言之前,先深入了解一种语言(我个人推荐Python)。