实习小记-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 ...
随机推荐
- EffectiveJava——用函数对象表示策略
有些语言支持函数指针.代理.lambda表达式,或者支持类似的机制,允许程序把“调用特殊函数的能力”储存起来并传递这种能力.这种机制通常用于允许函数的调用者通过传入第二个函数,来指定自己的行为.比较器 ...
- 亲们! 首次见面! 带来不适!多多见谅!--------->>Bank系统
亲们!您们好! 讲一下Bank系统的做法: 01.首先创建一个Card类 using System; using System.Collections.Generic; using System.Li ...
- Python生成器、迭代器、可迭代对象
把一个列表[]改成()就创建了一个生成器:generator,generator保存的是算法. 可以用于for循环的数据类型:1.集合类型:list tuple dict set str2.gener ...
- mysql 5.6.33发布
2016-09-06,mysql 5.6.33社区版发布,修复的bug越发减少,而且基本上都是较少使用的特性.
- 你可以使用 play framework 做5件很爽的事情http://www.anool.net/?p=629
1.绑定HTTP参数到JAVA方法里的参数. 使用PLAY可以很简单的从JAVA代码中检索HTTP参数.只要把方法参数申明成和HTTP参数相同既可. 比如,这个request: Http代码 /art ...
- 一些js小题(一)
一些js小题,掌握这些对于一些常见的面试.笔试题应该很有帮助: var a=10; function aa(){ alert(a); } function bb(){ aa(); } bb();//1 ...
- AloneJs.confirmbox() —— 确认框
一.引用 <link href="https://cdn.suziyun.com/alonejs.min.css" rel="stylesheet" /& ...
- andriod VideoView
package com.example.yanlei.myyk; import android.media.MediaPlayer; import android.net.Uri; import an ...
- android:#FFFFFFFF 颜色码解析
原文地址:android:#FFFFFFFF 颜色作者:android小鸟 颜色色码为#FFFFFFFF 其中颜色顺序依次为#AARRGGBB 前两位AA代表透明度,FF时表示不透明,00表示透明: ...
- Purchase购物车实例分析
源代码下载地址:http://code4app.com/ios/55655def933bf09d328b5141 此源代码从中学到以下四个知识点 第一:关于右边只有一个被选中的效果展现,左边部分代码内 ...