2013-01-06 19 views
1

我可以使这个代码工作,但我仍然困惑为什么它不会以我尝试的第一种方式工作。从python中的另一个文件导入类 - 我知道修正,但为什么不是原来的工作?

我正在练习python,因为我的论文将被编码(使用Arduino和PC界面来做一些很酷的事情)。我试图从另一个文件导入一个类到我的主程序,以便我可以创建对象。这两个文件都在同一个目录中。如果您现在查看代码,可能会更容易。

#from ArduinoBot import * 
#from ArduinoBot import ArduinoBot 
import ArduinoBot 

# Create ArduinoBot object 
bot1 = ArduinoBot() 

# Call toString inside bot1 object 
bot1.toString() 

input("Press enter to end.") 

这是非常基本的ArduinoBot类

class ArduinoBot: 

def toString(self): 
    print ("ArduinoBot toString") 

无论是前两个注释掉的import语句将会使这项工作,但不是最后一个,这对我来说似乎是最直观,最普遍。在这里没有很多代码出错,当我听到关于Python的许多好东西时,碰到这种尖锐的语言特定怪癖有点令人沮丧。无论如何,我必须做错了什么,但为什么不简单的'导入ClassName'或'导入FileName'工作?

谢谢你的帮助。在你的主程序

class foo(object): 
    pass 

class bar(object): 
    pass 

class example(object): 
    pass 

现在,如果你这样做:

+0

实际上'导入FileName'的作品,只要文件在你的$ PYTHONPATH。 – adamsmith

+1

这根本不是“挑剔的”。在第一种情况下,您将模块的整个名称空间导入本地名称空间。在第二种情况下,您将模块名称空间中的一个类导入到本地名称空间中。第三,您将模块本身导入到本地名称空间,因此,您必须以其成员身份访问其成员。如果你没有像你的类一样命名你的文件(这真的是Java的东西),或许就像'arduino_lib',那么它可能会更清晰。 –

+1

@ sr2222 - 我通常在它们所在的模块之后避免命名类,但是至少有一个stdlib模块('datetime')有先例。 – mgilson

回答

5

考虑文件(example.py

import example 

又该文件example.py进口?只有班级examplefoo也应该出现吗?如果import module将整个模块的名称空间直接拖到当前名称空间中,则含义太模糊。

这个想法是命名空间是美好的。他们让你知道类/函数/数据来自哪里。他们还让你把相关的东西组合在一起(或者等价地,它们可以帮助你把不相关的东西分开!)。一个模块设置了一个名称空间,并通过您使用import的方式告诉python您想如何将该名称空间带入当前上下文(名称空间)。

from ... import *表示 - 将该模块中的所有内容直接放入我的名称空间中。

from ... import ... as ...说,只把我指定的东西直接带到我的名字空间,但在这里给它一个新的名字。

最后,import ...只是说把这个模块放到当前的命名空间中,但要保持它的独立性。由于(至少)2个原因,这是生产代码中最常见的形式。

  • 它可以防止名称冲突。你可以有一个名为foo局部类,不会与fooexample.py冲突 - 你可以通过example.foo
  • 它可以很容易地跟踪下来哪个模块中的一类,从调试来获得访问该。

考虑:

from foo import * 
from bar import * 
a = AClass() #did this come from foo? bar? ... Hmmm... 

在这种情况下,从example.py获取到类example访问,你也可以这样做:

import example 
example_instance = example.example() 

,但你也可以得到foo

foo_instance = example.foo() 
+0

我想这只是一种不同的思考方式 - 对我来说,导入FileX意味着我想从该文件导入所有类。如果他们想要明确,但这不是一个大问题,至少我明白为什么现在不工作。谢谢。来自python('import this')的禅宗的 – user1262553

+0

:“显式比隐式更好”。如果你想隐式,使用'from ... import *'。每种形式的进口都是不同的 - 如果2种形式做了同样的事情,那也会与禅宗产生冲突(“应该有一种 - 最好只有一种 - 明显的做法”)。虽然, “起初,这种方式可能并不明显,除非你是荷兰人。” ;-) – mgilson

+1

为什么这有意义?模块本身是一个对象,是“模块”类的一个实例。如果导入一个模块导入了它的所有组件,那么你将会放弃模块本身的对象性的许多好处。 –

0

导入不起作用,你认为它确实如此。它工作是记录在案的工作方式,因此有对你的问题的一个非常简单的补救措施,但还是:

import ArduinoBot 

这看起来对进口路径上的模块(或包),执行模块代码放在新的名称空间中,然后将模块对象本身绑定到当前名称空间中的名称ArduinoBot。这意味着ArduinoBot模块中名为ArduinoBot的模块全局变量现在可以在导入名称空间中作为ArduinoBot.ArduinoBot访问。

from ArduinoBot import ArduinoBot 

这载荷并如上所述执行的模块,但模块对象不结合到名称ArduinoBot。而是在模块内查找模块全局变量ArduinoBot,并绑定当前名称空间中引用名称ArduinoBot的任何对象。

from ArduinoBot import * 

与上述类似,这会加载并执行模块,而不将模块对象绑定到当前名称空间中的任何名称。然后它会查找全部模块全局变量,并将它们全部绑定到当前名称空间中的相同名称。

最后的形式是在Python Shell交互工作很方便,但一般认为是不好的风格在实际开发中,因为它不是清楚什么名字,它实际上结合。考虑到它进口一切全球进口模块中,包括在全球范围内引进任何名字,它很快变得非常难以知道是什么名字的范围或他们来自何处,如果你使用普遍地这种风格来了。

0

简单的答案是模块是Python中的东西。模块作为类,函数和其他对象的容器具有自己的状态。当您执行import ArduinoBot时,您将导入模块。如果你想要那个模块中的东西 - 类,函数等 - 你必须明确地说你想要它们。您可以直接使用from ArduinoBot import ...导入它们,也可以通过模块import ArduinoBot然后ArduinoBot.ArduinoBot访问它们。

,而不是针对这方面的工作,你应该利用模块的容器的烦躁,让您将相关材料到模块。当你在一个文件中只有一个类时,看起来似乎很烦人,但是当你开始在一个文件中放入多个类和函数时,你会发现当你做import module时,你实际上并不希望所有的东西都被自动导入,因为那么来自所有模块的所有内容都会与其他事物相冲突这些模块在分离不同功能方面提供了有用的功能。

对于你的例子,你应该问自己的问题是:如果代码非常简单和紧凑,为什么不把它全部放在一个文件中?

0

模块本身是一个对象。如果您作为模块的成员访问您的课程,最后一种方法确实可行。无论是如果下面的工作,并且要么可能是适当的,这取决于你从进口商品需要些什么:

from my_module import MyClass 
foo = MyClass() 

import my_module 
foo = my_module.MyClass() 

正如在评论中提到,你的模块和类通常在Python中没有相同的名称。这更像是一件Java事情,有时可能会导致一些混乱。

相关问题