代码之家  ›  专栏  ›  技术社区  ›  Björn Pollex

使用自定义哈希函数创建namedtuple

  •  17
  • Björn Pollex  · 技术社区  · 15 年前

    说我有一个 namedtuple 这样地:

    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
    

    那么,我能做什么?或者这完全是个坏主意,我应该从头开始写我自己的课?

    1 回复  |  直到 12 年前
        1
  •  28
  •   LukáÅ¡ Lalinský    15 年前

    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
    
        2
  •  11
  •   ipetrik    5 年前

    从python3.6.1开始,使用 typing.NamedTuple 类(只要您对类型提示没有问题):

    from typing import NamedTuple, Any
    
    
    class FooTuple(NamedTuple):
        item1: Any
        item2: Any
    
        def __hash__(self):
            return hash(self.item1) * hash(self.item2)
    
        3
  •  0
  •   Community CDub    5 年前

    namedtuple 有一个习惯 __hash__ 函数用于存储 immutable data models 进入之内 dict set

    例如:

    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)])
    

    __eq__ __散列__ 允许将业务分组到 设置 ,确保每个业务线在集合中是唯一的:

    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
    
    推荐文章