具有自定义哈希行为的 python 对象集

2023-12-10

我想使用一个集合来管理“myItem”实例的集合。 myItem 类有自己的哈希函数。 这些项目的哈希值基于每个项目中的部分数据,但不是全部数据,为简单起见,在下面的示例中,“数据”是字典 r。哈希考虑了 2 个键 hk1 和 hk2,还有第三个键“sad”在哈希计算中未考虑。

class myItem():

    def __init__(self, r):
        # r is a dict holding information about the instance
        # of course r has to have certain keys...
        self.r = r

    def __hash__(self):
        """Override the default hash behavior"""
        return hash(tuple(sorted([self.r['hk1'],self.r['hk2']])))

    def __eq__(self,other):
        """checking equality"""
        if isinstance(other, self.__class__):
            return self.__hash__() == other.__hash__()
        return NotImplemented

    def __ne__(self, other):
        """checking inequality"""
        if isinstance(other, self.__class__):
            return not self.__eq__(other)
        return NotImplemented

    def __repr__(self):
        return str(self.r)

下面的简短单元测试证实了预期的行为。

class testMySet(unittest.TestCase):

    def testMyItemstuff(self):

        m1 = myItem({'hk1':'val1', 'hk2': 100, 'sad': 'other stuff'})
        m2 = myItem({'hk1': 'val1', 'hk2': 100, 'sad': 'different other stuff'})

        self.assertEqual(m1, m2)
        self.assertNotEqual(m1.r['sad'], m2.r['sad'])

        s = { m1 }
        # add m2 to s
        s.add(m2)
        # same hash, m2 is not added
        self.assertEqual(len(s), 1)
        # set contains the original object, not the last one added
        self.assertNotEqual(s.pop().r['sad'], 'different other stuff')

我的问题是,如何修改行为,以便添加一个散列与现有对象一致的新对象最终取代原始对象,同时对性能影响最小?


以这种方式定义哈希对您的应用程序是否有意义确实由您决定,但这似乎不太可能。

无论如何,我可以想到两个选项“与”集合一样快 - O(1) 而不是 O(n) - 它们的速度取决于实现您所描述的哈希函数:

首先,简化您的类并创建实例:

class Item():
    def __init__(self, a, b):
        self.a = a
        self.b = b

    def __hash__(self):
        return hash(self.a)

    def __eq__(self,other):
        if isinstance(other, self.__class__):
            # Ignoring .b attribute
            return self.a == other.a
        else:
            return NotImplemented

    def __repr__(self):
        return "Item(%s, %s)" % (self.a, self.b)

i1 = Item(1,2)
i2 = Item(3,4)
i3 = Item(1,5)


print(i1 == i2)             # False (.a's don't match)
print(i1 == i3)             # True  (.a's match)

方法一:字典值

# Using a dict
updating_set = {}
updating_set[i1] = i1       # .values(): [Item(1, 2)]
updating_set[i2] = i2       # .values(): [Item(1, 2), Item(3, 4)]
updating_set[i3] = i3       # .values(): [Item(1, 5), Item(3, 4)]

print(list(updating_set.values()))
# [Item(1, 5), Item(3, 4)]

方法2:使用集合子类

# Using a set subclass
class UpdatingSet(set):
    def add(self, item):
        if item in self: super().remove(item)
        super().add(item)

uset = UpdatingSet()
uset.add(i1)                # UpdatingSet({Item(1, 2)})
uset.add(i2)                # UpdatingSet({Item(1, 2), Item(3, 4)})
uset.add(i3)                # UpdatingSet({Item(1, 5), Item(3, 4)})

奖励方法 3:不需要特殊的哈希函数

class NewItem():
    def __init__(self, a, b):
        self.a = a
        self.b = b

    def __repr__(self):
        return "Item(%s, %s)" % (self.a, self.b)

class ItemSet():
    def __init__(self):
        self.items = {}

    def add(self, item):
        item_hash = item.a
        self.items[item_hash] = item

    def values(self):
        return self.items.values()

i1 = NewItem(1,2)
i2 = NewItem(3,4)
i3 = NewItem(1,5)

iset = ItemSet()
iset.add(i1)                # .values(): [Item(1, 2)]
iset.add(i2)                # .values(): [Item(1, 2), Item(3, 4)]
iset.add(i3)                # .values(): [Item(1, 5), Item(3, 4)]

print(list(iset.values()))  # [Item(1, 5), Item(3, 4)]

第三种方法不需要您实施hash(这可能会导致意想不到的副作用,但模仿内部的哈希过程ItemSet.add(),使用“哈希函数”作为字典键。

这可能是你最好的选择,除非你really想要实施哈希并了解该决定的影响程度。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

具有自定义哈希行为的 python 对象集 的相关文章

  • Django REST序列化器:创建对象而不保存

    我已经开始使用 Django REST 框架 我想做的是使用一些 JSON 发布请求 从中创建一个 Django 模型对象 然后使用该对象而不保存它 我的 Django 模型称为 SearchRequest 我所拥有的是 api view
  • 如何生成给定范围内的回文数列表?

    假设范围是 1 X 120 这是我尝试过的 gt gt gt def isPalindrome s check if a number is a Palindrome s str s return s s 1 gt gt gt def ge
  • Pycharm Python 控制台不打印输出

    我有一个从 Pycharm python 控制台调用的函数 但没有显示输出 In 2 def problem1 6 for i in range 1 101 2 print i end In 3 problem1 6 In 4 另一方面 像
  • 如何在Windows上模拟socket.socketpair

    标准Python函数套接字 套接字对 https docs python org 3 library socket html socket socketpair不幸的是 它在 Windows 上不可用 从 Python 3 4 1 开始 我
  • Python tcl 未正确安装

    我刚刚为 python 安装了graphics py 但是当我尝试运行以下代码时 from graphics import def main win GraphWin My Circle 100 100 c Circle Point 50
  • 从列表中的数据框列中搜索部分字符串匹配 - Pandas - Python

    我有一个清单 things A1 B2 C3 我有一个 pandas 数据框 其中有一列包含用分号分隔的值 某些行将包含与上面列表中的一项的匹配 它不会是完美的匹配 因为它在其中包含字符串的其他部分 该列 例如 该列中的一行可能有 哇 这里
  • Python 中的二进制缓冲区

    在Python中你可以使用StringIO https docs python org library struct html用于字符数据的类似文件的缓冲区 内存映射文件 https docs python org library mmap
  • python 集合可以包含的值的数量是否有限制?

    我正在尝试使用 python 设置作为 mysql 表中 ids 的过滤器 python集存储了所有要过滤的id 现在大约有30000个 这个数字会随着时间的推移慢慢增长 我担心python集的最大容量 它可以包含的元素数量有限制吗 您最大
  • Python:字符串不会转换为浮点数[重复]

    这个问题在这里已经有答案了 我几个小时前写了这个程序 while True print What would you like me to double line raw input gt if line done break else f
  • ExpectedFailure 被计为错误而不是通过

    我在用着expectedFailure因为有一个我想记录的错误 我现在无法修复 但想将来再回来解决 我的理解expectedFailure是它会将测试计为通过 但在摘要中表示预期失败的数量为 x 类似于它如何处理跳过的 tets 但是 当我
  • Python:尝试检查有效的电话号码

    我正在尝试编写一个接受以下格式的电话号码的程序XXX XXX XXXX并将条目中的任何字母翻译为其相应的数字 现在我有了这个 如果启动不正确 它将允许您重新输入正确的数字 然后它会翻译输入的原始数字 我该如何解决 def main phon
  • 如何改变Python中特定打印字母的颜色?

    我正在尝试做一个简短的测验 并且想将错误答案显示为红色 欢迎来到我的测验 您想开始吗 是的 祝你好运 法国的首都是哪里 法国 随机答案不正确的答案 我正在尝试将其显示为红色 我的代码是 print Welcome to my Quiz be
  • 通过数据框与函数进行交互

    如果我有这样的日期框架 氮 EG 00 04 NEG 04 08 NEG 08 12 NEG 12 16 NEG 16 20 NEG 20 24 datum von 2017 10 12 21 69 15 36 0 87 1 42 0 76
  • Python 3 中“map”类型的对象没有 len()

    我在使用 Python 3 时遇到问题 我得到了 Python 2 7 代码 目前我正在尝试更新它 我收到错误 类型错误 map 类型的对象没有 len 在这部分 str len seed candidates 在我像这样初始化它之前 se
  • 在Python中重置生成器对象

    我有一个由多个yield 返回的生成器对象 准备调用该生成器是相当耗时的操作 这就是为什么我想多次重复使用生成器 y FunctionWithYield for x in y print x here must be something t
  • VSCode:调试配置中的 Python 路径无效

    对 Python 和 VSCode 以及 stackoverflow 非常陌生 直到最近 我已经使用了大约 3 个月 一切都很好 当尝试在调试器中运行任何基本的 Python 程序时 弹出窗口The Python path in your
  • 如何从没有结尾的管道中读取 python 中的 stdin

    当管道来自 打开 时 不知道正确的名称 我无法从 python 中的标准输入或管道读取数据 文件 我有作为例子管道测试 py import sys import time k 0 try for line in sys stdin k k
  • 从 Python 中的类元信息对 __init__ 函数进行类型提示

    我想做的是复制什么SQLAlchemy确实 以其DeclarativeMeta班级 有了这段代码 from sqlalchemy import Column Integer String from sqlalchemy ext declar
  • 循环标记时出现“ValueError:无法识别的标记样式 -d”

    我正在尝试编码pyplot允许不同标记样式的绘图 这些图是循环生成的 标记是从列表中选取的 为了演示目的 我还提供了一个颜色列表 版本是Python 2 7 9 IPython 3 0 0 matplotlib 1 4 3 这是一个简单的代
  • Pandas 与 Numpy 数据帧

    看这几行代码 df2 df copy df2 1 df 1 df 1 values 1 df2 ix 0 0 我们的教练说我们需要使用 values属性来访问底层的 numpy 数组 否则我们的代码将无法工作 我知道 pandas Data

随机推荐

  • 我应该在 href="" 中使用 & 还是在 HTML4 和 HTML5 中 & 就足够了?

    我应该使用 amp in href or HTML4 和 HTML5 就够了吗 大多数浏览器都没有问题 但是应该如何完成呢 a href param1 1 param2 2 Call a Or a href quest param1 1 a
  • 从 Tkinter Tcl 回调 python 函数在 Windows 中崩溃

    这不完全是我的应用程序 但非常相似 我创建了这个测试代码来显示问题 基本上我试图从 python 线程调用 tcl proc 当结果准备好时 Tcl proc 将回调到 python 函数 该结果将作为事件发布到 wx 框架 当我作为纯 p
  • Android发布密钥库问题:“密钥库被篡改,或密码不正确”

    几个月前 我使用以下命令生成了 Android 版本密钥库 keytool genkey v keystore my release key keystore alias myalias keyalg RSA keysize 2048 va
  • 从最新到最旧读取事件日志

    我编写了一个简短的程序 使用启动和关闭时发布的事件日志消息来确定远程 PC 的正常运行时间 目前的逻辑是 foreach eventlogentry if entryTime gt OldestTime if entry Startup a
  • Spring MVC不加载css、js文件到静态html页面

    我禁用了该角色内部视图解析器为了访问一些静态页面 html not jsp页面 我做了所需的更改 确实我做了并且我可以访问我的html页面 但是当我看到浏览器的控制台时 它看起来好像没有带来我的本地css and js files 这是我的
  • 在 Ruby 中访问 JSON 对象 [关闭]

    Closed 这个问题需要调试细节 目前不接受答案 我有一个 json 文件 看起来像这样 Results Lookup null Result Paths Domain VALUE1 LTD Url Text1 Modules Name
  • 如何编辑文件夹/文件的修改日期?

    我正在使用 webdav 和 HttpWebRequest MKCOL 方法在 SP 中创建文件夹 我使用 WebClient 上传文件 对于上传的文件和创建的文件夹 如何设置其修改日期 我正在寻找类似的东西Directory SetLas
  • Swift 5:转义闭包捕获“inout”参数

    我已经有了从服务器收到的响应数据 这个响应数据有一些面包师数据 现在我想计算用户和面包店的距离 然后将其存储在同一个模态类中 我为它创建了一个函数 由于这个函数需要在 4 5 视图控制器中使用 我的计划是创建为 UIViewControll
  • 如何在 Python 中使用 ctypes 卸载 DLL?

    我正在使用 ctypes 在 Python 中加载 DLL 这很好用 现在我们希望能够在运行时重新加载该 DLL 直接的方法似乎是 1 卸载DLL 2 加载DLL 不幸的是我不确定卸载 DLL 的正确方法是什么 ctypes FreeLib
  • 创建自定义 Powershell 对象的多个实例

    我正在 Powershell 脚本中创建一个新对象 或者实际上是一个对象类型 我想创建该对象的多个实例 我该怎么做呢 下面的代码是我正在处理的代码 看起来数组中的所有实例都引用相同的对象 包含相同的值 Define output objec
  • DART:有人可以向我解释一下这句话吗?

    我正在学习 Dart 和 Flutter 但我正在努力解决一些基本的编程问题 例如 getter 的使用 GoogleSignInAccount get user gt user 与 get 方法等效的是什么 什么是 变量末尾的意思是什么
  • 在 Sublime Text 2 中使用默认的 ruby​​ 版本

    我的默认当前 ruby 版本是 1 9 3 它实际上是我运行时出现的唯一版本rvm list所以我不明白我怎么能把那部分搞乱 我确实关注了this我在这里找到的教程 但它似乎破坏了一切 对于我看到的修复程序的所有变体 甚至在评论中 我不断收
  • 通过 AWS Data Pipelines 运行 python 脚本

    我使用 AWS Data Pipelines 运行夜间 SQL 查询 以填充表以获取摘要统计信息 用户界面有点时髦 但最终我安装并运行了 现在我想用 python 脚本做类似的事情 我有一个每天早上在笔记本电脑上运行的文件 forecast
  • 是否可以在不使用 lambda 的情况下将标准函数模板之一作为参数传递?

    例如 std get
  • PDO-MySQL:在准备好的语句绑定上布尔值被转换为 1 或空字符串

    我正在尝试将一些布尔值插入到 JSON 类型列中 taskSql INSERT INTO Tasks data taskListId VALUES JSON OBJECT title title done done taskListId t
  • UICollectionView 单元格与图像,单击更改背景

    我有一个UICollectionView with Custom CollectionView Cells 每个Cell上都有一个Image 它和整个Cell一样大 现在我想在用户触摸单元格时突出显示该单元格 首先我尝试了以下方法deleg
  • Apps 脚本与 Chrome 扩展:编写 Google 文档的替代拼写检查器

    Say 我想开发一个替代谷歌文档的拼写检查模块 这意味着我必须从后端获取更正 并对拼写错误的文本的背景进行着色 并在用户将鼠标悬停在其上方时弹出一个小气泡 在其中显示更正 请注意 拼写检查不是我项目的实际目标 但它确实以更简化的方式解决了我
  • 计算 Pandas 中字符串列中的单词数

    我有一个 pandas 数据框 其中包含给定时间段的查询和计数 我希望将此数据框转换为唯一单词的计数 例如 如果数据框包含以下内容 query count foo bar 10 super 8 foo 4 super foo bar 2 我
  • 外部表的格式不符合预期。

    我正在创建一个小应用程序来将 Excel 数据导入我的数据库 当我单击按钮时 它崩溃并出现错误 外部表的格式不符合预期 我尝试在谷歌上搜索并更改代码 但问题仍然出现 我尝试将文件另存为 xls 当我运行代码时 页面与 google chro
  • 具有自定义哈希行为的 python 对象集

    我想使用一个集合来管理 myItem 实例的集合 myItem 类有自己的哈希函数 这些项目的哈希值基于每个项目中的部分数据 但不是全部数据 为简单起见 在下面的示例中 数据 是字典 r 哈希考虑了 2 个键 hk1 和 hk2 还有第三个