实习小记-python 内置函数__eq__函数引发的探索
乱写__eq__会发生啥?请看代码..
>>> class A:
... def __eq__(self, other): # 不论发生什么,只要有==做比较,就返回True
... return True
...
>>> a = A()
>>> b = A()
>>> a == b
True
>>> a != b # 这个地方为什么会返回False?
False
>>> a > b
Traceback (most recent call last):
File "<ipython-input-7-1e61210fe837>", line 1, in <module>
a > b
TypeError: unorderable types: A() > A() >>> x = [1,2,3,b,4,5]
>>> x.index(b) # 咦?
0
>>> x.index(2)
1
>>> x.index(4) # 诶?
3
>>> x.index(5) # 艾玛,啥情况?
3
>>> x.index(6) # 妈呀!
3
>>> x.index(a) # 23333
0
当时初次看到这个就被这神奇的现象吸引了,发现新大陆了的感觉。以为发现了BUG。。。问我隔壁的小哥,也说不明白。但可以确定的是,如果我没有重写这个__eq__函数的话,下面的操作都是正常的,找不到的就找不到,能找到的就返回正确的index。所以肯定是我__eq__函数写差了,源码看不到也不好搜索,于是跑去看文档。文档这里写道:
- object.__lt__(self, other)
- object.__le__(self, other)
- object.__eq__(self, other)
- object.__ne__(self, other)
- object.__gt__(self, other)
- object.__ge__(self, other)
These are the so-called “rich comparison” methods. The correspondence between operator symbols and method names is as follows: x<y calls x.__lt__(y), x<=y calls x.__le__(y), x==y calls x.__eq__(y), x!=y calls x.__ne__(y), x>y calls x.__gt__(y), and x>=y calls x.__ge__(y).
A rich comparison method may return the singleton NotImplemented if it does not implement the operation for a given pair of arguments. By convention, False and True are returned for a successful comparison. However, these methods can return any value, so if the comparison operator is used in a Boolean context (e.g., in the condition of an if statement), Python will call bool() on the value to determine if the result is true or false.
There are no implied relationships among the comparison operators. The truth of x==y does not imply that x!=y is false. Accordingly, when defining __eq__(), one should also define __ne__() so that the operators will behave as expected. See the paragraph on __hash__() for some important notes on creating hashable objects which support custom comparison operations and are usable as dictionary keys.
There are no swapped-argument versions of these methods (to be used when the left argument does not support the operation but the right argument does); rather, __lt__() and __gt__() are each other’s reflection, __le__() and __ge__() are each other’s reflection, and __eq__() and __ne__() are their own reflection.
Arguments to rich comparison methods are never coerced.
To automatically generate ordering operations from a single root operation, see functools.total_ordering().
-
1.这些比较函数都称为rich comparison,正常情况下,它们回返回真或假。实际上这些函数都可以返回任意类型的值,如果这些比较被运用在布尔环境中的时候,比方说if 语句的条件中时,python 会调用bool()函数来确认当前的返回值是真还是假。(划横线的地方不会翻译=。=)
2.这些函数的定义之间并没有引申的含义,比如说如果a==b是真,并不代表a!=b一定是假。所以我们在定义__eq__函数的时候也应该同时定义__ne__函数以确保我们能够得到我们想要的结果。如果我们想了解可哈希对象的比较的信息,我们最好去看看__hash__()的文档。这里就不展开了,具体文章在这里(实习小记-python中可哈希对象是个啥?what is hashable object in python?)
3.这些函数并没有可替换参数之说(像是左边的参数不支持这个函数,而右边的参数支持。)这里要说的是,__lt__()函数和__gt__()函数他们两个的取值是一定相反的;__le__()和__ge__()也一定是取相反的;但是__eq__()函数和__ne__()函数是各自独立定义的。相互之间并没有关系。这也就是2里面提到的。
4.比较这类操作的参数是不会类型转换的。(如果a,b做比较,a是浮点,b是整数,比较结束后b不会变成浮点类型?)
5.如果我们希望能够在一些情况下自动排序,那么请参考functools.total_ordering()
读到这里我们在回到之前的代码中看看,到底发生了什么
>>> class A:
... def __eq__(self, other): # 不论发生什么,只要有==做比较,就返回True
... return True
...
>>> a = A()
>>> b = A()
>>> a == b
True
>>> a != b # 这个地方为什么会返回False?
False
>>> a > b
Traceback (most recent call last):
File "<ipython-input-7-1e61210fe837>", line 1, in <module>
a > b
TypeError: unorderable types: A() > A() >>> x = [1,2,3,b,4,5]
>>> x.index(b) # 首先拿x中的1与b做比较,应该是==的比较,由于b.__eq__()无论什么情况下都返回True。所以python以为第一个元素就是b,于是返回index 0
0
>>> x.index(2)
1
>>> x.index(4) # 这里拿4做比较,x中的元素安顺序比较,1,2,3为False,但当比较到b时由于b的坑爹属性返回True,以为找到了,返回index 3
3
>>> x.index(5) # 同上
3
>>> x.index(6) # 同上
3
>>> x.index(a) # 和第一次相比的原因是一样的。
0那么问题来了,如果我们需要一种类,该类的实例做比较的时候比较类中属性,属性相等返回True,在列表中查找时也能正确查找,应该如何写呢?请看下面代码:
>>> class A:
... def __init__(self, x):
... self.x = x
... def __eq__(self, other):
... try:
... return self.x == other.x
... except AttributeError:
... return False
... def __ne__(self, other):
... try:
... return self.x != other.x
... except AttributeError: # 发现两者不可比,返回类型错误
... raise TypeError('this two argument is not comparable!')
...
>>> a = A(1)
>>> b = A(1)
>>> c = A(2)
>>> a == b
True
>>> a != b
False
>>> a == c
False
>>> a != c # 相同类型做比较,确实不相同
True
>>> a == 1 # 不同类型做比较,返回False
False
>>> a != 1 # 判断不同类型是否不等,报类型错误
Traceback (most recent call last):
File "<ipython-input-52-30ec16ffc1a6>", line 1, in <module>
a != 1
File "<ipython-input-43-70049527ba59>", line 13, in __ne__
raise TypeError('this two argument is not comparable!')
TypeError: this two argument is not comparable! >>> list = [1,2,3,b,4,5]
>>> list.index(3)
2
>>> list.index(b) # 成功找到!
3
>>> list.index(a) # 实例不同,但是self.x相等,属于同一个。
3
>>> a in list
True
>>> b in list
True
实习小记-python 内置函数__eq__函数引发的探索的更多相关文章
- python 练习题:请利用Python内置的hex()函数把一个整数转换成十六进制表示的字符串
# -*- coding: utf-8 -*- # 请利用Python内置的hex()函数把一个整数转换成十六进制表示的字符串 n1 = 255 n2 = 1000 print(hex(n1)) pr ...
- Python内置高阶函数map()
map()函数map()是 Python 内置的高阶函数,它接收一个函数 f 和一个 list,并通过把函数 f 依次作用在 list 的每个元素上,得到一个新的 list 并返回. 例如,对于lis ...
- 匿名函数python内置高阶函数以及递归
匿名函数 python定义一个函数通常使用def关键词,后面跟函数名,然后是注释.代码块等. def func(): '''注释''' print('from func') 这样就在全局命名空间定义了 ...
- Python - 内置函数 选例
概览参见 https://www.runoob.com/python/python-built-in-functions.html 官方文档 https://docs.python.org/3/li ...
- Python内置函数二 (递归函数,匿名函数,二分法)
匿名函数 lambda() 语法: lambad 参数 : 返回值 def func(a,b): return a * b print(func(2,5)) a = lambda a ,b : a* ...
- 熟记这些python内置函数,你离大佬就不远了
python内置了很多函数,方便我们在写程序的时候调用,在ython 2.7 的所有内置函数共有80个.熟练记住和使用这些内置函数,将大大提高写Python代码的速度和代码的优雅程度. 以下代码示例用 ...
- 【转】实习小记-python 内置函数__eq__函数引发的探索
[转]实习小记-python 内置函数__eq__函数引发的探索 乱写__eq__会发生啥?请看代码.. >>> class A: ... def __eq__(self, othe ...
- python内置函数
python内置函数 官方文档:点击 在这里我只列举一些常见的内置函数用法 1.abs()[求数字的绝对值] >>> abs(-13) 13 2.all() 判断所有集合元素都为真的 ...
- 【转】python 内置函数总结(大部分)
[转]python 内置函数总结(大部分) python 内置函数大讲堂 python全栈开发,内置函数 1. 内置函数 python的内置函数截止到python版本3.6.2,现在python一共为 ...
- python内置函数,匿名函数
一.匿名函数 匿名函数:为了解决那些功能很简单的需求而设计的一句话函数 def calc(n): return n**n print(calc(10)) #换成匿名函数 calc = lambda n ...
随机推荐
- CSS 选择器汇总
CSS 选择器 CSS 元素选择器 CSS 选择器分组 CSS 类选择器详解 CSS ID 选择器详解 CSS 属性选择器详解 CSS 后代选择器 CSS 子元素选择器 CSS 相邻兄弟选择器 CSS ...
- 主程序底部TabBar功能跟登录页面布局
1:主程序底部TabBar的功能实现 效果图: 主要代码如下: - (UITabBarController*)setRootVC:(BOOL)bShowCart { //创建一个子控制器 用于显示当前 ...
- Effective Java 阅读笔记——方法
38:检查参数的有效性 每当编写方法或者构造器的时候,应该考虑它的参数有哪些限制,在方法的开头处对参数进行检查,并且把这些限制写入文档. 注意: 对于公有方法,应该使用@throws标签在文档中说明违 ...
- 无需cygwin,使用NDK进行开发
NDK从7开始自带编译器,在windows上无需配置cygwin的环境. 在eclips中配置NDK路径 在eclipse中点击菜单栏window-Perferences,配置NDK的路径. 在工程中 ...
- 如何在Eclipse卸载之前添加的android 的 ADT
Android开发环境配置中,怎么卸载ADT? 在Android开发环境配置中,可能会遇到很多问题,其中ADT安装失败需要卸载,怎么卸载呢?下面讲一种方法,希望能够对你有所帮助. 我采用的是Eclip ...
- Jenkins部署.net自动化构建
1.环境部署: windows server 2008R2环境 2.相关软件 SVN(源代码管理器:jenkins通过插件从源代码管理器下载代码) Jenkins(主角)地址:http://f ...
- 更轻量的 View Controllers
iew controllers 通常是 iOS 项目中最大的文件,并且它们包含了许多不必要的代码.所以 View controllers 中的代码几乎总是复用率最低的.我们将会看到给 view con ...
- iOS开发笔记12:iOS7上UITextField限制字数输入导致崩溃问题
在一些场景中,需要限制用户的输入字数,例如在textField里进行控制(textView也类似,崩溃原因也相同),如图所示 系统会监听文本输入,需要注意的第一点是输入法处于联想输入还未确定提交的时候 ...
- iOS开发笔记7:Text、UI交互细节、两个动画效果等
Text主要总结UILabel.UITextField.UITextView.UIMenuController以及UIWebView/WKWebView相关的一些问题. UI细节主要总结界面交互开发中 ...
- Xcode6.4注册URL Scheme步骤详解
URL Scheme的作用 我们都知道苹果手机中的APP都有一个沙盒,APP就是一个信息孤岛,相互是不可以进行通信的.但是iOS的APP可以注册自己的URL Scheme,URL Scheme是为方便 ...