2

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

文件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。谁能解释发生了什么?

4

2 回答 2

1

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

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

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

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

于 2013-08-26T08:36:25.177 回答
-2

当你这样做时

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)
于 2013-08-26T08:44:02.347 回答