繁体   English   中英

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

[英]Importing class from another file in python - I know the fix, but why doesn't the original work?

我可以使此代码正常工作,但是我仍然困惑为什么它不能以我尝试的第一种方式起作用。

我正在练习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的好消息时遇到这些挑剔的语言怪癖,这真让人沮丧。 无论如何,我一定做错了什么,但是为什么简单的'import ClassName'或'import FileName'不起作用?

谢谢您的帮助。

考虑一个文件( 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的本地类,该类不会与example.pyfoo冲突-您可以通过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()

导入并不像您认为的那样有效。 确实按照记录的方式工作,因此有一个非常简单的补救措施可以解决您的问题,但是:

import ArduinoBot

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

from ArduinoBot import ArduinoBot

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

from ArduinoBot import *

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

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

简单的答案是模块就是Python中的东西。 模块作为类,函数和其他对象的容器具有其自身的状态。 当您import ArduinoBot ,您将导入模块。 如果您想要该模块中的内容(类,函数等),则必须明确地说出您想要它们。 您可以使用from ArduinoBot import ...直接导入它们,也可以通过先import ArduinoBot然后使用ArduinoBot.ArduinoBot的模块访问它们。

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

对于您的示例,您应该问自己的问题是:如果代码是如此简单和紧凑,为什么不将所有内容都放在一个文件中?

模块本身是一个对象。 如果您以模块的成员身份访问类,则最后一种方法实际上是可行的。 以下哪种方法都可以,或者哪种都合适,这取决于您还需要从导入项中获取什么:

from my_module import MyClass 
foo = MyClass()

要么

import my_module
foo = my_module.MyClass()

如注释中所述,您的模块和类在python中通常没有相同的名称。 这更多是Java的事情,有时可能会引起一些混乱。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM