![](/img/trans.png)
[英]Why python's monkeypatch doesn't work when importing a class instead of a module?
[英]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.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()
导入并不像您认为的那样有效。 它确实按照记录的方式工作,因此有一个非常简单的补救措施可以解决您的问题,但是:
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.