从python中的另一个文件导入类我知道修复方法,但为什么原来的方法不起作用?

2024-05-28 23:07:50 发布

您现在位置:Python中文网/ 问答频道 /正文

我可以让这段代码正常工作,但我仍然不明白为什么我第一次尝试的方法不起作用。在

我在练习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类

^{pr2}$

前两个被注释掉的import语句中的任何一个都可以实现这一点,但最后一个却不行,这在我看来是最直观和最一般的。这里没有太多的代码会出错,当我听到Python的一些好消息时,碰到这种针对特定语言的挑剔的怪癖让我有点沮丧。不管怎么说,我一定是做错了什么,但是为什么简单的“import ClassName”或“import FileName”不起作用呢?在

谢谢你的帮助。在


Tags: 文件方法代码fromimport目录object事情
3条回答

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

与此相反,您应该利用模块的容器性来允许您将相关的内容分组到一个模块中。当您在一个文件中只有一个类时,这可能看起来很烦人,但是当您开始将多个类和函数放在一个文件中时,您会发现实际上您并不希望在执行import module时自动导入所有这些内容,因为这样一来,来自所有模块的所有内容都会与其他内容发生冲突。这些模块在分离不同的功能时起到了有用的作用。在

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

导入并不像你想象的那样有效。它的工作方式与文档中记录的工作方式相同,因此对于您的问题有一个非常简单的解决方法,但是:

import ArduinoBot

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

^{pr2}$

它如上所述加载并执行模块,但不将模块对象绑定到名称ArduinoBot。相反,它在模块中查找模块全局变量ArduinoBot,并绑定引用当前命名空间中名称ArduinoBot的任何对象。在

from ArduinoBot import *

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

最后一个表单对于pythonshell中的交互工作非常方便,但是在实际开发中通常被认为是不好的样式,因为它不清楚它实际绑定了什么名称。考虑到它在导入的模块中导入所有全局的,包括在global scope导入的任何名称,如果您普遍使用这种样式,很快就会非常难知道哪些名称在作用域中或它们来自何处。在

考虑一个文件(example.py):

class foo(object):
    pass

class bar(object):
    pass

class example(object):
    pass

现在在您的主程序中,如果您这样做:

^{pr2}$

应该从文件example.py导入什么?只是类example?类foo也应该一起来吗?{{5>直接拉入你当前的名称空间。在

其想法是名称空间非常棒。它们让您知道类/函数/数据来自何处。它们还可以让你把相关的东西放在一起(或者等效地,它们帮助你把不相关的东西分开!)。一个模块设置一个名称空间,然后通过使用import的方式确切地告诉python如何将该名称空间引入当前上下文(名称空间)。在

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

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

最后,import ...简单地说,将该模块放入当前的名称空间中,但将其分开。这是生产代码中最常见的形式,因为(至少)两个原因。在

  • 它可以防止名称冲突。您可以有一个名为foo的本地类,它不会与example.py中的foo冲突——您可以通过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()

相关问题 更多 >

    热门问题