1

我可以使这段代码工作,但我仍然很困惑为什么它不能以我尝试的第一种方式工作。

我正在练习 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 的好消息时,遇到这些挑剔的语言特定的怪癖有点令人沮丧。无论如何,我一定是做错了什么,但为什么简单的“导入类名”或“导入文件名”不起作用?

谢谢您的帮助。

4

4 回答 4

5

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

class foo(object):
    pass

class bar(object):
    pass

class example(object):
    pass

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

import example

应该从文件中导入什么example.py?只是上课example?班级也应该一foo起来吗?import module如果将整个模块的名称空间直接拉到您当前的名称空间中,则含义将过于模糊。

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

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

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

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

  • 它可以防止名称冲突。你可以有一个名为的本地类foo,它不会与fooin冲突example.py——你可以通过example.foo
  • 它可以很容易地跟踪一个类来自哪个模块以进行调试。

考虑:

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

example在这种情况下,要从访问类example.py,您还可以执行以下操作:

import example
example_instance = example.example()

但你也可以得到foo

foo_instance = example.foo()
于 2013-01-06T04:31:47.947 回答
1

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

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

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

于 2013-01-06T04:51:28.377 回答
0

模块本身就是一个对象。如果您以模块成员的身份访问您的类,最后一种方法实际上确实有效。以下是否可行,或者是否合适,具体取决于您对导入项目的其他需求:

from my_module import MyClass 
foo = MyClass()

或者

import my_module
foo = my_module.MyClass()

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

于 2013-01-06T05:01:51.027 回答
0

导入并不像您认为的那样工作。它确实按照文档记录的方式工作,因此有一个非常简单的解决方法可以解决您的问题,但尽管如此:

import ArduinoBot

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

from ArduinoBot import ArduinoBot

这会像上面一样加载并执行模块,但不会将模块对象绑定到 name ArduinoBot。相反,它在模块中查找模块全局变量,并绑定在当前命名空间ArduinoBot中引用该名称的任何对象。ArduinoBot

from ArduinoBot import *

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

最后一种形式非常方便在 python shell 中进行交互工作,但在实际开发中通常被认为是不好的样式,因为不清楚它实际绑定了哪些名称。考虑到它会在导入的模块中导入所有全局内容,包括它在全局范围内导入的任何名称,如果您普遍使用这种样式,那么很快就很难知道范围内的名称或它们的来源。

于 2013-01-06T04:49:45.297 回答