假设我有一个namedtuple这样的:
EdgeBase = namedtuple("EdgeBase", "left, right")我想为此实现一个自定义哈希函数,所以我创建了以下子类:
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中的子类化和初始化,特别是与元组。 这个解决方案有什么缺陷吗? 有没有推荐的方法如何做到这一点? 好吗 提前致谢。
Suppose I have a namedtuple like this:
EdgeBase = namedtuple("EdgeBase", "left, right")I want to implement a custom hash-function for this, so I create the following subclass:
class Edge(EdgeBase): def __hash__(self): return hash(self.left) * hash(self.right)Since the object is immutable, I want the hash-value to be calculated only once, so I do this:
class Edge(EdgeBase): def __init__(self, left, right): self._hash = hash(self.left) * hash(self.right) def __hash__(self): return self._hashThis appears to be working, but I am really not sure about subclassing and initialization in Python, especially with tuples. Are there any pitfalls to this solution? Is there a recommended way how to do this? Is it fine? Thanks in advance.
最满意答案
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__中创建,然后返回给用户,而不是在__init__填充数据。
由于__new__因为历史/奇怪的原因隐含地是一个staticmethod方法,所以cls必须被传递给__new__的super调用两次。
edit for 2017: turns out namedtuple isn't a great idea. attrs is the modern alternative.
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__ is what you want to call here because tuples are immutable. Immutable objects are created in __new__ and then returned to the user, instead of being populated with data in __init__.
cls has to be passed twice to the super call on __new__ because __new__ is, for historical/odd reasons implicitly a staticmethod.
更多推荐
发布评论