|
4 | 4 | <qhelp> |
5 | 5 |
|
6 | 6 | <overview> |
7 | | -<p>In order to conform to the object model, classes should define either no equality methods, or both |
8 | | -an equality and an inequality method. If only one of <code>__eq__</code> or <code>__ne__</code> is |
9 | | -defined then the method from the super class is used. This is unlikely to result in the expected |
10 | | -behavior.</p> |
| 7 | +<p>In order to ensure the <code>==</code> and <code>!=</code> operators behave consistently as expected (i.e. they should be negations of each other), care should be taken when implementing the |
| 8 | +<code>__eq__</code> and <code>__ne__</code> special methods.</p> |
| 9 | + |
| 10 | +<p>In Python 3, if the <code>__eq__</code> method is defined in a class while the <code>__ne__</code> is not, |
| 11 | +then the <code>!=</code> operator will automatically delegate to the <code>__eq__</code> method in the expected way. |
| 12 | + </p> |
| 13 | + |
| 14 | + <p>However, if the <code>__ne__</code> method is defined without a corresponding <code>__eq__</code> method, |
| 15 | + the <code>==</code> operator will still default to object identity (equivalent to the <code>is</code> operator), while the <code>!=</code> |
| 16 | + operator will use the <code>__ne__</code> method, which may be inconsistent. |
| 17 | + |
| 18 | +<p>Additionally, if the <code>__ne__</code> method is defined on a superclass, and the subclass defines its own <cde>__eq__</code> method without overriding |
| 19 | +the superclass <code>__ne__</code> method, the <code>!=</code> operator will use this superclass <code>__ne__</code> method, rather than automatically delegating |
| 20 | +to <code>__eq__</code>, which may be incorrect. |
11 | 21 |
|
12 | 22 | </overview> |
13 | 23 | <recommendation> |
14 | 24 |
|
15 | | -<p>When you define an equality or an inequality method for a class, remember to implement both an |
16 | | -<code>__eq__</code> method and an <code>__ne__</code> method.</p> |
| 25 | +<p>Ensure that when an <code>__ne__</code> method is defined, the <code>__eq__</code> method is also defined, and their results are consistent. |
| 26 | +In most cases, the <code>__ne__</code> method does not need to be defined at all, as the default behavior is to delegate to <code>__eq__</code> and negate the result. </p> |
17 | 27 |
|
18 | 28 | </recommendation> |
19 | 29 | <example> |
20 | | -<p>In the following example the <code>PointOriginal</code> class defines an equality method but |
21 | | -no inequality method. If this class is tested for inequality then a type error will be raised. The |
22 | | -<code>PointUpdated</code> class is better as it defines both an equality and an inequality method. To |
23 | | -comply fully with the object model this class should also define a hash method (identified by |
24 | | -a separate rule).</p> |
| 30 | +<p>In the following example, <code>A</code> defines a <code>__ne__</code> method, but not an <code>__eq__</code> method. |
| 31 | +This leads to inconsistent results between equality and inequality operators. |
| 32 | +</p> |
| 33 | + |
| 34 | +<sample src="examples/EqualsOrNotEquals1.py" /> |
| 35 | + |
| 36 | +<p>In the following example, <code>C</code> defines an <code>__eq__</code> method, but its <code>__ne__</code> implementation is inherited from <code>B</code>, |
| 37 | +which is not consistent with the equality operation. |
| 38 | +</p> |
25 | 39 |
|
26 | | -<sample src="EqualsOrNotEquals.py" /> |
| 40 | +<sample src="examples/EqualsOrNotEquals2.py" /> |
27 | 41 |
|
28 | 42 | </example> |
29 | 43 | <references> |
30 | 44 |
|
31 | 45 |
|
32 | | -<li>Python Language Reference: <a href="http://docs.python.org/2/reference/datamodel.html#object.__ne__">object.__ne__</a>, |
33 | | -<a href="http://docs.python.org/2/reference/expressions.html#comparisons">Comparisons</a>.</li> |
| 46 | +<li>Python Language Reference: <a href="http://docs.python.org/3/reference/datamodel.html#object.__ne__">object.__ne__</a>, |
| 47 | +<a href="http://docs.python.org/3/reference/expressions.html#comparisons">Comparisons</a>.</li> |
34 | 48 |
|
35 | 49 |
|
36 | 50 | </references> |
|
0 commit comments