Python判断两个对象相等的原理


Posted in Python onDecember 12, 2017

概述

大部分的python程序员平时编程的时候,很少关心两个对象为什么相等,因为教程和经验来说,他们就应该相等,比如1==1就应该返回True,可是当我们想要定义自己的对象或者修改默认的对象行为时,通常会因为不了解原理而导致各种奇奇怪怪的错误。

两个对象如何相等

两个对象如何才能相等要比我们想象的复杂很多,但核心的方法是重写 eq 方法,这个方法返回True,则表示两个对象相等,否则,就不相等。相反的,如果两个对象不相等,则重写 ne 方法。 默认情况下,如果你没有实现这个方法,则使用父类(object)的方法。父类的方法比较是的两个对象的ID(可以通过id方法获取对象ID),也就是说,如果对象的ID相等,则两个对象也就相等。因此,我们可以得知,默认情况下,对象只和自己相等。例如:

>>> class A(object):
...  pass
...
>>>
>>> a = A()
>>> b = A()
>>> a == a
True
>>> a == b
False
>>> id(a)
4343310992
>>> id(b)
4343310928

Python2程序员经常犯的一个错误是,只重写了 eq 方法,而没有重写 ne 方法,导致不可预计的错误。而Python3会自动重写 ne 方法,如果你没有重写的话。

对象的Hash方法

Python里可Hash的对象,都有一个数字ID代表了它在python里的值,这个ID是由对象的 hash 方法返回的。因此,如果想让一个对象可Hash,那必须实现 hash 方法和之前提到的 eq 方法。和对象相等一样,默认情况下,对象的 hash 方法继承自Object对象,而Object对象的 hash 方法只计算对象ID,因此两个对象始终拥有两个不一样的hash id,不管他们是多么相似。 当我们把一个不可Hash的对象加入到set或者dict时,会发生什么了?

>>> set().add({})
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'dict'
unhashable type: 'dict'

原因是set()和dict()使用对象的hash值作为内部索引,以便能快速索引到指定对象。因此,同一个对象返回相同的hash id就很重要了。

对象的Hash值在它的生命周期内不能改变

如果你想定义一个比较完美的对象,并且实现了 eq 和 hash 方法来定义对象的比较行为和hash值,那么你就需要保证对象的相关属性不能发生更改。不然会导致很诡异的错误,比如下面的例子。

>>> class C:
...  def __init__(self, x):
...   self.x = x
...  def __repr__(self):
...   return "C({"+str(self.x)+"})"
...  def __hash__(self):
...   return hash(self.x)
...  def __eq__(self, other):
...   return (
...    self.__class__ == other.__class__ and
...    self.x == other.x
...   )
>>> d = dict()
>>> s = set()
>>> c = C(1)
>>> d[c] = 42
>>> s.add(c)
>>> d, s
({C(1): 42}, {C(1)})
>>> c in s and c in d # c is in both!
True
>>> c.x = 2
>>> c in s or c in d # c is in neither!?
False
>>> d, s
({C(2): 42}, {C(2)}) # but...it's right there!

在我们没有修改对象的属性时(c.x=2)之前,所有行为都符合预期。当我们通过c.x=2时修改属性后,执行c in s or c in d返回False,但是内容却是修改后的,是不是很奇怪。这也就解释了为什么str、tuple是可Hash的,而list和dict是不可hash的。

因此我们可以得出结论,如果两个对象相等的话,那它们的hash值必然也是相等的。

总结

讲了这么多有什么用了。 1. 当我们遇到unhashable type这个异常时,我们能够知道为什么报这个错误。 2. 如果定义了一个可比较的对象,那么最好保证对象hash值相关的属性在生命周期内不能发生改变,不然会发生意想不到的错误。

以上所述是小编给大家介绍的Python判断两个对象相等的原理,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Python 相关文章推荐
python根据路径导入模块的方法
Sep 30 Python
Python中threading模块join函数用法实例分析
Jun 04 Python
使用django-guardian实现django-admin的行级权限控制的方法
Oct 30 Python
Python实现合并excel表格的方法分析
Apr 13 Python
Pytorch卷积层手动初始化权值的实例
Aug 17 Python
opencv3/C++实现视频背景去除建模(BSM)
Dec 11 Python
Python3打包exe代码2种方法实例解析
Feb 17 Python
python GUI库图形界面开发之PyQt5开发环境配置与基础使用
Feb 25 Python
Python中zip函数如何使用
Jun 04 Python
Python Opencv图像处理基本操作代码详解
Aug 31 Python
python爬虫框架feapde的使用简介
Apr 20 Python
Django实现drf搜索过滤和排序过滤
Jun 21 Python
浅谈Django REST Framework限速
Dec 12 #Python
Django admin美化插件suit使用示例
Dec 12 #Python
Django admin实现图书管理系统菜鸟级教程完整实例
Dec 12 #Python
基于Django filter中用contains和icontains的区别(详解)
Dec 12 #Python
Python有序查找算法之二分法实例分析
Dec 11 #Python
django实现用户登陆功能详解
Dec 11 #Python
Python通过Django实现用户注册和邮箱验证功能代码
Dec 11 #Python
You might like
PHP安全配置
2006/10/09 PHP
php通过文件头检测文件类型通用代码类(zip,rar等)
2010/10/19 PHP
PHP在线书签系统分享
2016/01/04 PHP
Thinkphp5.0 框架使用模型Model添加、更新、删除数据操作详解
2019/10/11 PHP
jQuery1.4.2与老版本json格式兼容的解决方法
2011/02/12 Javascript
使用GruntJS构建Web程序之合并压缩篇
2014/06/06 Javascript
使用jQuery和Bootstrap实现多层、自适应模态窗口
2014/12/22 Javascript
javascript中cookie对象用法实例分析
2015/01/30 Javascript
jquery.gridrotator实现响应式图片展示画廊效果
2015/06/23 Javascript
文字垂直滚动之javascript代码
2015/07/29 Javascript
JS实现的简洁二级导航菜单雏形效果
2015/10/13 Javascript
node.js回调函数之阻塞调用与非阻塞调用
2015/11/13 Javascript
jquery实现横向图片轮播特效代码分享
2015/11/19 Javascript
yii form 表单提交之前JS在提交按钮的验证方法
2017/03/15 Javascript
浅谈Vue.js 1.x 和 2.x 实例的生命周期
2017/07/25 Javascript
JavaScript中附件预览功能实现详解(推荐)
2017/08/15 Javascript
详解bootstrap-fileinput文件上传控件的亲身实践
2019/03/21 Javascript
转换layUI的数据表格中的日期格式方法
2019/09/19 Javascript
如何优雅地在Node应用中进行错误异常处理
2019/11/25 Javascript
vue使用echarts图表自适应的几种解决方案
2020/12/04 Vue.js
[04:55]完美世界副总裁蔡玮:DOTA2的自由、公平与信任
2013/12/18 DOTA
使用python编写脚本获取手机当前应用apk的信息
2014/07/21 Python
python多重继承新算法C3介绍
2014/09/28 Python
Python 12306抢火车票脚本 Python京东抢手机脚本
2018/02/06 Python
TensorFlow神经网络优化策略学习
2018/03/09 Python
python中time库的实例使用方法
2019/10/31 Python
Pycharm修改python路径过程图解
2020/05/22 Python
python正则表达式re.match()匹配多个字符方法的实现
2021/01/27 Python
轻松掌握CSS3中的字体大小单位rem的使用方法
2016/05/24 HTML / CSS
商务助理岗位职责
2013/11/13 职场文书
期中考试反思800字
2014/05/01 职场文书
学雷锋演讲稿汇总
2014/05/10 职场文书
2014年政协工作总结
2014/12/09 职场文书
优秀党员事迹材料
2014/12/18 职场文书
云台山导游词
2015/02/03 职场文书
SQL Server内存机制浅探
2022/04/06 SQL Server