Python奇怪错误:“TypeError:'NoneType'对象不可调用”

时间:2011-07-31 18:34:00

标签: python

我正在实现一个简单的类来表示2D矢量。以下是相关内容:

class Vector:
  def __init__( self, x, y ):
    self.vec_repr = x, y

  def __add__( self, other ):
    new_x = self.x + other.x
    new_y = self.y + other.y
    return Vector( new_x, new_y )

  def __getattr__( self, name ):
    if name == "x":
      return self.vec_repr[0]
    elif name == "y":
      return self.vec_repr[1]

稍后,我有类似的事情:

a = Vector( 1, 1 )
b = Vector( 2, 2 )
a + b

我得到TypeError: 'NoneType' object is not callable。这特别奇怪,因为错误没有标记为在任何特定的行上,所以我不知道在哪里看!

非常奇怪,所以我做了一些实验,发现它发生在a+b行上。另外,当我重新上课时,如下:

class Vector:
  def __init__( self, x, y ):
    self.x, self.y = x, y

  def __add__( self, other ):
    new_x = self.x + other.x
    new_y = self.y + other.y
    return Vector( new_x, new_y )

错误消失了!

我看到有很多关于类似于此的错误的问题 - 所有似乎都涉及某个函数名称被某个变量覆盖,但我看不出这发生了什么!

作为另一个线索,当我将__getattr__()的默认返回类型更改为其他内容时 - 例如str - 错误变为TypeError: 'str' object is not callable

关于发生了什么的任何想法?是否有一些我不理解的__getattr__()行为?

1 个答案:

答案 0 :(得分:11)

问题是您的__getattr__不会为xy以外的属性返回任何内容,也不会引发AttributeError。因此,当查找__add__方法时,__getattr__会返回None,从而返回错误。

您可以通过为其他属性返回__getattr__值来解决此问题。实际上,您必须确保__getattr__从其超类调用未处理的所有属性的方法。但真的__getattr__在这里使用是错误的。它应该谨慎使用,并且当没有更明显的,更高级别的解决方案可用时。例如,__getattr__对动态调度至关重要。但在您的情况下,xy值在代码运行之前是众所周知且定义良好的。

正确的解决方案是制作xy属性,而不是实现__getattr__

@property
def x(self):
    return self.vec_repr[0]

@property
def y(self):
    return self.vec_repr[1]