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列表(list)、字典(dict)、字符串(string)基本操作小结
Nov 28 Python
Python 中迭代器与生成器实例详解
Mar 29 Python
Python使用pymysql从MySQL数据库中读出数据的方法
Jul 25 Python
Python3爬虫之自动查询天气并实现语音播报
Feb 21 Python
python字符串Intern机制详解
Jul 01 Python
Python内存管理实例分析
Jul 10 Python
Pandas中DataFrame的分组/分割/合并的实现
Jul 16 Python
Python远程开发环境部署与调试过程图解
Dec 09 Python
django admin后管定制-显示字段的实例
Mar 11 Python
Django自定义列表 models字段显示方式
Apr 03 Python
Python爬取微信小程序Charles实现过程图解
Sep 29 Python
Python内置函数及功能简介汇总
Oct 13 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
DOTA2 1月28日更新:监管系统降临刀塔世界
2021/01/28 DOTA
判断是否为指定长度内字符串的php函数
2010/02/16 PHP
非常实用的PHP常用函数汇总
2014/12/17 PHP
PHP数组相关函数汇总
2015/03/24 PHP
PHP安装GeoIP扩展根据IP获取地理位置及计算距离的方法
2016/07/01 PHP
php.ini中date.timezone设置详解
2016/11/20 PHP
PHP实现截取中文字符串不出现?号的解决方法
2016/12/29 PHP
thinkphp5框架实现的自定义扩展类操作示例
2019/05/16 PHP
基于thinkphp5框架实现微信小程序支付 退款 订单查询 退款查询操作
2020/08/17 PHP
精通Javascript系列之Javascript基础篇
2011/06/07 Javascript
使用apply方法实现javascript中的对象继承
2013/12/16 Javascript
跟我学Node.js(四)---Node.js的模块载入方式与机制
2014/06/04 Javascript
jquery仿苹果的时间/日期选择效果
2017/03/08 Javascript
jquery拖动改变div大小
2017/07/04 jQuery
highcharts 在angular中的使用示例代码
2017/09/20 Javascript
vue.js 底部导航栏 一级路由显示 子路由不显示的解决方法
2018/03/09 Javascript
Vue.js实现可编辑的表格
2019/12/11 Javascript
react基本安装与测试示例
2020/04/27 Javascript
.netcore+vue 实现压缩文件下载功能
2020/09/24 Javascript
Python Web框架Flask中使用百度云存储BCS实例
2015/02/08 Python
Python3 读、写Excel文件的操作方法
2018/10/20 Python
python单线程下实现多个socket并发过程详解
2019/07/27 Python
python+Selenium自动化测试——输入,点击操作
2020/03/06 Python
使用Python FastAPI构建Web服务的实现
2020/06/08 Python
意大利宠物用品购物网站:Bauzaar
2018/09/15 全球购物
顺丰快递Java软件工程师面试题
2015/07/31 面试题
无偿献血倡议书
2014/04/14 职场文书
《与朱元思书》的教学反思
2014/04/17 职场文书
关于梦想的演讲稿
2014/05/05 职场文书
2014年重阳节老干部座谈会上的讲话稿
2014/09/25 职场文书
2014年向国旗敬礼活动总结
2014/09/27 职场文书
兵马俑导游词
2015/02/02 职场文书
结婚十年感言
2015/07/31 职场文书
车辆管理制度范本
2015/08/05 职场文书
小学生安全教育主题班会
2015/08/12 职场文书
致运动员的广播稿
2015/08/19 职场文书