在类中使用import

时间:2016-06-28 22:06:15

标签: python class import

我对python类概念完全陌生。在寻找解决方案几天后,我希望我能在这里得到帮助:

我想要一个python类,我在其中导入一个函数并在那里使用它。主代码应该能够从类中调用该函数。因为我在同一个文件夹中有两个文件。

感谢@cdarke,@ DeepSpace和@MosesKoledoye,我编辑了这个错误,但遗憾的是那不是它。

我仍然得到错误:

test 0
Traceback (most recent call last):
  File "run.py", line 3, in <module>
    foo.doit()
  File "/Users/ls/Documents/Entwicklung/RaspberryPi/test/test.py", line 8, in doit
    self.timer(5)
  File "/Users/ls/Documents/Entwicklung/RaspberryPi/test/test.py", line 6, in timer
    zeit.sleep(2)
NameError: global name 'zeit' is not defined

@wombatz得到了正确的提示: 它必须是self.zeit.sleep(2)或Test.zeit.sleep(2)。导入也可以在类声明之上完成。

Test.Py

class Test:
    import time as zeit
    def timer(self, count):
        for i in range(count):
            print("test "+str(i))
            self.zeit.sleep(2)      <-- self is importent, otherwise, move the import above the class declaration
    def doit(self):
        self.timer(5)

run.py

from test import Test
foo = Test()
foo.doit()

当我尝试python run.py时,我收到此错误:

test 0
Traceback (most recent call last):
  File "run.py", line 3, in <module>
    foo.doit()
  File "/Users/ls/Documents/Entwicklung/RaspberryPi/test/test.py", line 8, in doit
    self.timer(5)
  File "/Users/ls/Documents/Entwicklung/RaspberryPi/test/test.py", line 6, in timer
    sleep(2)
NameError: global name 'sleep' is not defined

我从错误中理解的是,无法识别类中的导入。但是我如何才能认识到班级中的导入是否被认可?

6 个答案:

答案 0 :(得分:10)

必须从该类访问类的名称空间中定义的所有内容。这适用于方法,变量,嵌套类以及包括模块在内的所有其他内容。

如果您真的想在类中导入模块,则必须从该类访问它:

class Test:
    import time as zeit
    def timer(self):
        self.zeit.sleep(2)
        # or Test.zeit.sleep(2)

但是为什么要在课程中导入模块呢?我不能想到一个用例,尽管它希望它放入该命名空间。

您真的应该将导入移动到模块的顶部。然后,您可以在课程内拨打zeit.sleep(2),而不必在selfTest前加上。

此外,您不应使用zeit之类的非英语标识符。只会说英语的人应该能够阅读你的代码。

答案 1 :(得分:3)

sleep不是内置的python,名称不是,它不引用任何对象。所以Python正确地提出了NameEror

您打算:

import time as zeit

zeit.sleep(2)

import time as zeit移至模块顶部。

time模块别名zeit可能没有出现在您模块的全局符号表中,因为它是在class内导入的。

答案 2 :(得分:3)

你想要time.sleep。你也可以使用;

from time import sleep

编辑:在类范围内导入问题here解释。

答案 3 :(得分:2)

你快到了! sleeptime模块中的一个函数。这意味着名称sleep不存在,除非您在time的上下文中理解它,除非您自己定义它。由于您没有自己定义,因此可以通过运行time.sleep(2)来访问它。

在您的具体示例中,您使用了:

import time as zeit

你必须跑:

zeit.sleep(2) 

或者,您可以通过运行以下方式直接导入睡眠:

from time import sleep
sleep(2)
祝你好运!

您可以在此处详细了解时间模块:https://docs.python.org/2/library/time.html

您可以在此处了解有关导入的更多信息:https://docs.python.org/3/reference/import.html

我强烈建议在python中学习命名空间,在这里:https://bytebaker.com/2008/07/30/python-namespaces/

答案 4 :(得分:0)

我同意@Wombatz的解决方案,但是我没有足够的声誉来评论他的问题

我发现要在类中导入模块的一种用例是当我想从配置文件初始化类时。

说我的配置文件是

config.py

__all__ = ['logfile', ... ]
logfile = 'myevent.log'
...

在我的主模块中

do_something.py

class event():
    from config import *

    def __init__(self):
        try : self.logfile
        except NameError: self.logfile = './generic_event.log'

现在该方案的优点是,如果不需要,我们不需要在全局名称空间中导入日志文件

鉴于此,在do_something.py开头导入时,我将不得不在类内部使用全局变量,这在我看来有点难看。

答案 5 :(得分:0)

这可能有点晚了,但我同意不污染模块级命名空间的想法(当然,这可能可以通过更好的模块设计来补救,加上无论如何“显式优于隐式”)。< /p>

这就是我要做的。基本思想是这样的:import 是一种隐式赋值,其中将整个模块对象分配给单个名称。因此:

class Test:
    import time as zeit
    
    self.zeit = zeit # This line binds the module object to an attribute of an instance created from the class
    
    def timer(self, count):
        for i in range(count):
            print("test "+str(i))
            self.zeit.sleep(2) # This necessitates the `zeit` attribute within the instance created from the class
    
    def doit(self):
        self.timer(5)