在Python中,是否应该将_une_uu实现为对_eq_u的否定?
我有一个类,我想重写在Python中,是否应该将_une_uu实现为对_eq_u的否定?,python,comparison,operators,inequality,python-datamodel,Python,Comparison,Operators,Inequality,Python Datamodel,我有一个类,我想重写\uuuuueq\uuu方法。我也应该重写\uu\ne\uu方法,这似乎是有道理的。我应该将\uu ne\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu A类: 定义初始化(自我,状态): self.state=状态 定义(自身、其他): 返回self.state==other.state 定义(自身、其他): 返回非自我。均衡(其他) 是的,
\uuuuueq\uuu
方法。我也应该重写\uu\ne\uu
方法,这似乎是有道理的。我应该将\uu ne\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
A类:
定义初始化(自我,状态):
self.state=状态
定义(自身、其他):
返回self.state==other.state
定义(自身、其他):
返回非自我。均衡(其他)
是的,那很好。事实上,当您定义\uuuuu eq\uuuu
时,会敦促您定义\uuuu ne\uuuuu
:
没有隐含的关系
在比较运算符中。这个
x==y的真理并不意味着x=y
这是错误的。因此,在定义
\uuuu eq\uuuu()
,还应定义\uuuu ne\uuuuuu()
,以便运算符按预期运行
在很多情况下(比如这一个),它会像否定\uuuuueq\uuuuu
的结果一样简单,但并不总是如此。如果所有\uuuuuueq\uuuuu
、\uuuu lt\uuuuuuu
、\uge\uuge\ucode>、和/ucmp>代码都对类有意义,那么就实现代码吧。否则,就照你现在做的去做,因为Daniel DiPaolo说过(当我测试它而不是查找它时;)
Python,我应该基于\uuu eq\uu
实现\uu ne\uuu()操作符吗
简短回答:不要实现它,但如果必须,请使用=
,而不是\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
在Python3中,=
是默认情况下对==
的否定,因此您甚至不需要编写\uuu ne\uuuu
,文档也不再坚持编写一个
一般来说,对于Python3-only代码,除非需要掩盖父实现(例如,对于内置对象),否则不要编写代码
也就是说,请记住:
只有在以下情况下,\uuu ne\uuuuuuu
方法才会从\uuuu eq\uuuu
自动执行
超类中尚未定义\uuu ne\uu
。所以,如果你是
从内置继承,最好同时覆盖这两个
如果需要代码在Python2中工作,请遵循Python2的建议,它在Python3中也可以正常工作
在Python2中,Python本身不会自动实现任何与另一个操作相关的操作-因此,您应该根据==
而不是\uuuuuu eq.
来定义\uu ene.
。
例如
A类(对象):
定义(自身、其他):
返回self.value==other.value
定义(自身、其他):
return not self==其他#not `返回not self.uuu eq_uu(其他)`
看到证据了吗
- 基于
\uuu eq\uu
和
- 根本没有在Python2中实现
\uuu ne\uu
在下面的演示中提供了不正确的行为
长话短说
Python2的版本说:
比较运算符之间没有隐含的关系。这个
x==y的真理并不意味着x=y
为假。因此,当
定义\uuuu eq\uuuu()
,还应定义\uu ne\uuuuu()
,以便
操作员将按预期操作
这意味着如果我们用\uuuu eq\uuu
的倒数来定义\uu ne\uuuu
,我们可以得到一致的行为
本节文档已针对以下内容进行了更新:
默认情况下,\uuu ne\uuu()
委托给\uu eq\uu()
,并反转结果
除非未实施
在中,我们看到这种行为发生了变化:
=
现在返回与==
相反的值,除非==
返回未实现
为了实现\uuu ne\uuu
,我们更喜欢使用=
操作符,而不是直接使用\uuuu eq\uuu
方法,这样,如果子类的self.\uu eq\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu(其他)
返回未实现的类型,Python将适当地检查其他
NotImplemented
对象
此类型只有一个值。只有一个对象具有此值。通过内置名称访问此对象
未实施
。数值方法和丰富的比较方法可能返回
如果不执行操作数的操作,则返回此值
假如(然后解释器将尝试反射操作,或
其他一些回退,取决于运算符。)其真值为
对
当给定一个丰富的比较运算符时,如果它们不是相同的类型,Python会检查other
是否是一个子类型,如果定义了该运算符,则首先使用other
的方法(与
相反)。如果返回NotImplemented
,则使用相反的方法。(它不会两次检查相同的方法。)使用==
运算符允许此逻辑发生
期望
从语义上讲,您应该在检查平等性方面实现\uu______
,因为您的类的用户希望以下函数对于一个类的所有实例都是等效的:
_等于(inst1,inst2)的定义否定:
“”“始终应返回与not_equals相同的值(inst1,inst2)”
返回not inst1==inst2
def不等于(inst1,inst2):
“”“始终应返回与_equals(inst1,inst2)的否定_相同的结果”
返回inst1!=inst2
也就是说,上述两个函数应始终返回相同的结果。但这取决于程序员
基于\uuuuu eq\uuuu
定义\uuuu ne\uuuuuuuu>时的意外行为演示:
首先,设置:
class BaseEqualable(对象):
assert not right1 == right2
assert not right2 == right1
assert right1 != right2
assert right2 != right1
assert not right_py3_1 == right_py3_2
assert not right_py3_2 == right_py3_1
assert right_py3_1 != right_py3_2
assert right_py3_2 != right_py3_1
assert not wrong1 == wrong2 # These are contradicted by the
assert not wrong2 == wrong1 # below unexpected behavior!
>>> assert wrong1 != wrong2
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AssertionError
>>> assert wrong2 != wrong1
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AssertionError
>>> right_py3_1, right_py3_1child = BaseEquatable(1), ChildComparablePy3(1)
>>> right_py3_1 != right_py3_1child # as evaluated in Python 2!
True
class Foo:
def __ne__(self, other):
return NotImplemented
__eq__ = __ne__
f = Foo()
f2 = Foo()
>>> f == f
True
>>> f != f
False
>>> f2 == f
False
>>> f2 != f
True
class CLevel:
"Use default logic programmed in C"
class HighLevelPython:
def __ne__(self, other):
return not self == other
class LowLevelPython:
def __ne__(self, other):
equal = self.__eq__(other)
if equal is NotImplemented:
return NotImplemented
return not equal
def c_level():
cl = CLevel()
return lambda: cl != cl
def high_level_python():
hlp = HighLevelPython()
return lambda: hlp != hlp
def low_level_python():
llp = LowLevelPython()
return lambda: llp != llp
>>> import timeit
>>> min(timeit.repeat(c_level()))
0.09377292497083545
>>> min(timeit.repeat(high_level_python()))
0.2654011140111834
>>> min(timeit.repeat(low_level_python()))
0.3378178110579029
class CStyle__ne__:
"""Mixin that provides __ne__ functionality equivalent to
the builtin functionality
"""
def __ne__(self, other):
equal = self.__eq__(other)
if equal is NotImplemented:
return NotImplemented
return not equal
import sys
class ...:
...
def __eq__(self, other):
...
if sys.version_info[0] == 2:
def __ne__(self, other):
equal = self.__eq__(other)
return equal if equal is NotImplemented else not equal
def __ne__(self, other):
return not self.__eq__(other)
def __ne__(self, other):
return not self == other
results = session.query(MyTable).filter(MyTable.fieldname != MyClassWithBadNE())
results = session.query(MyTable).filter(MyClassWithBadNE() != MyTable.fieldname)