如何为namedtuple的子类提供额外的初始化?

假设我有一个像这样的namedtuple

 EdgeBase = namedtuple("EdgeBase", "left, right") 

我想为此实现一个自定义的散列函数,所以我创build了下面的子类:

 class Edge(EdgeBase): def __hash__(self): return hash(self.left) * hash(self.right) 

由于对象是不可变的,所以我希望哈希值只能计算一次,所以我这样做:

 class Edge(EdgeBase): def __init__(self, left, right): self._hash = hash(self.left) * hash(self.right) def __hash__(self): return self._hash 

这似乎工作,但我真的不知道在Python的子类化和初始化,特别是与元组。 这个解决scheme有什么缺陷吗? 有一个build议的方式如何做到这一点? 好吗? 提前致谢。

 class Edge(EdgeBase): def __new__(cls, left, right): self = super(Edge, cls).__new__(cls, left, right) self._hash = hash(self.left) * hash(self.right) return self def __hash__(self): return self._hash 

__new__是你想在这里调用,因为元组是不可变的。 不可变对象在__new__中创build,然后返回给用户,而不是在__init__填充数据。

cls必须在__new__上被传递给super调用两次,因为__new__由于历史/奇怪的原因隐含地是staticmethod

问题中的代码可以从__init__中的超级调用中受益,以防在多重inheritance情况下被分类,否则是正确的。

 class Edge(EdgeBase): def __init__(self, left, right): super(Edge, self).__init__(a, b) self._hash = hash(self.left) * hash(self.right) def __hash__(self): return self._hash 

尽pipe元组只是只读的,但它们的子类的元组部分是只读的,其他属性可以像往常一样写,这就允许赋值_hash,而不pipe它是在__init__还是__new__ 。 您可以通过将__slots__设置为()来使子类完全只读,这有助于节省内存,但是您将无法将其指定给_hash。