Python 使用自定义哈希函数创建namedtuple
假设我有一个名为tuple的Python 使用自定义哈希函数创建namedtuple,python,inheritance,overriding,tuples,Python,Inheritance,Overriding,Tuples,假设我有一个名为tuple的,如下所示: FooTuple = namedtuple("FooTuple", "item1, item2") 我希望以下函数用于散列: foo_hash(self): return hash(self.item1) * (self.item2) 我之所以希望这样做,是因为我希望item1和item2的顺序不相关(我将对比较运算符执行相同的操作)。我想到了两种方法。第一个是: FooTuple.__hash__ = foo_hash 这是可行的,但感觉
,如下所示:
FooTuple = namedtuple("FooTuple", "item1, item2")
我希望以下函数用于散列:
foo_hash(self):
return hash(self.item1) * (self.item2)
我之所以希望这样做,是因为我希望item1
和item2
的顺序不相关(我将对比较运算符执行相同的操作)。我想到了两种方法。第一个是:
FooTuple.__hash__ = foo_hash
这是可行的,但感觉被黑客攻击了。因此,我尝试子类化FooTuple
:
class EnhancedFooTuple(FooTuple):
def __init__(self, item1, item2):
FooTuple.__init__(self, item1, item2)
# custom hash function here
但我明白了:
DeprecationWarning: object.__init__() takes no parameters
那么,我能做什么?或者这完全是一个坏主意,我应该从头开始编写自己的类吗?我认为您的代码有问题(我猜您创建了一个同名的元组实例,所以fooTuple
现在是一个元组,而不是元组类),因为这样子类化命名的元组应该可以工作。无论如何,您不需要重新定义构造函数。您只需添加哈希函数即可:
In [1]: from collections import namedtuple
In [2]: Foo = namedtuple('Foo', ['item1', 'item2'], verbose=False)
In [3]: class ExtendedFoo(Foo):
...: def __hash__(self):
...: return hash(self.item1) * hash(self.item2)
...:
In [4]: foo = ExtendedFoo(1, 2)
In [5]: hash(foo)
Out[5]: 2
从Python3.6.1开始,可以通过键入.NamedTuple
类更清晰地实现这一点(只要您对类型提示没有问题):
具有自定义函数的可用于存储到和中
例如:
class Point(namedtuple('Point', ['label', 'lat', 'lng'])):
def __eq__(self, other):
return self.label == other.label
def __hash__(self):
return hash(self.label)
def __str__(self):
return ", ".join([str(self.lat), str(self.lng)])
覆盖\uuuuu eq\uuuuuu
和\uuuuu hash\uuuuu
允许将业务分组到集合中,确保集合中的每个业务线都是唯一的:
walgreens = Point(label='Drugstore', lat = 37.78735890, lng = -122.40822700)
mcdonalds = Point(label='Restaurant', lat = 37.78735890, lng = -122.40822700)
pizza_hut = Point(label='Restaurant', lat = 37.78735881, lng = -122.40822713)
businesses = [walgreens, mcdonalds, pizza_hut]
businesses_by_line = set(businesses)
assert len(business) == 3
assert len(businesses_by_line) == 2
请注意,repr(foo)
仍将谈论foo
。这可以做得更好,因为类Foo(namedtuple('Foo',['item1','item2',verbose=False)):
注意@Sven的答案
walgreens = Point(label='Drugstore', lat = 37.78735890, lng = -122.40822700)
mcdonalds = Point(label='Restaurant', lat = 37.78735890, lng = -122.40822700)
pizza_hut = Point(label='Restaurant', lat = 37.78735881, lng = -122.40822713)
businesses = [walgreens, mcdonalds, pizza_hut]
businesses_by_line = set(businesses)
assert len(business) == 3
assert len(businesses_by_line) == 2