Python导入行为和'NoneType'对象没有属性

时间:2013-08-26 07:57:36

标签: python python-import

任何人都可以澄清以下行为。我在一段更大的代码中遇到了它,但我创建了一个最小的例子

文件untitled0.py包含以下代码:

import numpy as np
class A:
    def f(self,x):
        return np.diag(x)

文件untitled1.py包含以下代码:

import untitled0 as u0
import numpy as np
a=u0.A()
print a.f([1])

输出简单,并在屏幕上打印[[1]]。现在假设您已经创建了a(A的实例)并且需要大量的计算工作并继续编写脚本并且不想一直重新计算。我通常做的只是注释掉创建行(因为对象a已经存在于你的python shell中),即:。

import untitled0 as u0
import numpy as np
#a=u0.A()
print a.f([1])

但是,当我运行此脚本时会导致错误:

UMD has deleted: untitled0
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\WinPython-64bit-2.7.5.1\python-2.7.5.amd64\lib\site-packages\spyderlib\widgets\externalshell   \sitecustomize.py", line 523, in runfile
    execfile(filename, namespace)
  File "M:\....\untitled1.py", line 12, in <module>
    print a.f([1])
  File "untitled0.py", line 12, in f
    return np.diag(x)
AttributeError: 'NoneType' object has no attribute 'diag'

由于某些原因np未在untitled0.py内定义。谁能解释发生了什么?

2 个答案:

答案 0 :(得分:0)

“UMD已删除...”这一行是提示。您可能正在使用Spyder IDE,此处描述了这种非标准行为:Spyder - UMD has deleted: module

现在另外一个问题是unitled0.py模块已被卸载(并重新加载)。但是,预先存在的实例a具有一个类,该类是模块的旧副本中存在的类。因此,它的方法f()调用代码的旧版本。这里的问题是模块的旧副本是垃圾收集的:这意味着(奇怪的是)Python已经用None替换了所有全局名称。这就是您最终查找np.diag() ---但崩溃的原因,因为此时np为无。

为什么用None替换所有全局变量?这是一个非常古老的原因:因为它创建了引用循环,而且很久以前这样的循环用于创建内存泄漏。从那时起它就没有被清理过。

我很抱歉没有就如何避免这个问题提出具体的建议,但我希望这足以解释它是如何以及为什么的。我想进一步的讨论应该与Spyder的人一起讨论,你应该在那里报告问题以及它是如何出现的。

答案 1 :(得分:-1)

当你做

a.f([1]) 

评论时

 #a = u0.A()

发生的事情是a没有实例化。当a不存在时,无法调用其方法。这就是为什么解释器抛出“NoneType”属性没有名为diag的方法。而不必每次都重新计算结果,尝试通过改变f的行为将结果存储在a中;例如

class A:
    def f(self,no):
      self.result = np.diag(no)
      return self.result

然后再做

a = u0.A()
#use a 
a.f(some_list)