|
119 | 119 | }. %
|
120 | 120 | Therefore, \python\ also allows us to implement an \pythonilIdx{\_\_ne\_\_}\pythonIdx{dunder!\_\_ne\_\_} dunder method to realize inequality differently or, potentially, more efficiently, instead~\cite{PEP207}.
|
121 | 121 |
|
| 122 | +Finally, we compare whether \pythonil{p1} is the same as the integer number~\pythonil{5}. |
| 123 | +This, obviously, should return~\pythonil{False}. |
| 124 | +And it does so. |
| 125 | +This is because the two objects~\pythonil{p1} and~\pythonil{5} are not identical. |
| 126 | +The default equality comparison only checks for identity. |
| 127 | +If implement \pyhonilIdx{\_\_eq\_\_} by ourselves, this method should clearly return a value that makes \pythonil{p1 == 5} become~\pythonil{False} as well. |
| 128 | +Anything else would be nonsense. |
| 129 | + |
122 | 130 | \gitPython{\programmingWithPythonCodeRepo}{09_dunder/point_with_dunder.py}{--args format}{dunder:point_with_dunder}{%
|
123 | 131 | Our \pythonil{Point} class, extended with the \pythonilIdx{\_\_str\_\_}\pythonIdx{dunder!\_\_str\_\_}, \pythonilIdx{\_\_repr\_\_}\pythonIdx{dunder!\_\_repr\_\_}, and \pythonilIdx{\_\_eq\_\_}\pythonIdx{dunder!\_\_eq\_\_} dunder methods.}%
|
124 | 132 | %
|
|
129 | 137 | The concise string representation returned by \pythonilIdx{\_\_str\_\_}\pythonIdx{dunder!\_\_str\_\_} will just be the point coordinates in parentheses.
|
130 | 138 | This offers all the information needed at a glance, but it could be mistaken with a tuple as string.
|
131 | 139 | Therefore, the canonical string representation produced by \pythonilIdx{\_\_repr\_\_}\pythonIdx{dunder!\_\_repr\_\_} will return a string of the shape~\pythonil{"Point(x, y)"}.
|
| 140 | + |
132 | 141 | Finally, the \pythonilIdx{\_\_eq\_\_}\pythonIdx{dunder!\_\_eq\_\_} method will first check if the \pythonil{other} object is an instance of \pythonil{Point}.
|
133 | 142 | If so, it will return \pythonil{True} if and only if the \pythonil{x} and \pythonil{y} coordinate of the \pythonil{other} point are the same as of the point \pythonil{self}.
|
134 |
| -We can pack all of these conditions into one big \pythonilIdx{and} clause, because the evaluation of such clauses in \python\ is lazy: |
135 |
| -Only if \pythonil{isinstance(other, Point)}\pythonIdx{isinstance} is \pythonil{True}, the \pythonilIdx{and} clause can be \pythonil{True}. |
136 |
| -So the next condition \pythonil{other.x == self.x} is only evaluated in that case. |
137 |
| -Otherwise, if \pythonil{isinstance(other, Point)} is \pythonil{False}, the clause evaluation is stopped and \pythonil{False} is returned right away. |
| 143 | +Otherwise, it will return the constant \pythonilIdx{NotImplemented}:% |
| 144 | +% |
| 145 | +\quotation{PSF2024BIC}{% |
| 146 | +A special value which should be returned by the binary special methods [\dots] to indicate that the operation is not implemented with respect to the other type\dots\medskip\\\indent% |
| 147 | +\emph{Note:}~When a binary (or in-place) method returns \pythonilIdx{NotImplemented} the interpreter will try the reflected operation on the other type (or some other fallback, depending on the operator). % |
| 148 | +If all attempts return \pythonilIdx{NotImplemented}, the interpreter will raise an appropriate exception. % |
| 149 | +Incorrectly returning \pythonilIdx{NotImplemented} will result in a misleading error message or the \pythonilIdx{NotImplemented} value being returned to \python\ code. |
| 150 | +}% |
| 151 | +% |
| 152 | +In other words, our \pythonilIdx{\_\_eq\_\_} method can only compare the current~\pythonil{Point} for equality with another~\pythonil{Point}. |
| 153 | +If \pythonil{other} is not an instance of~\pythonil{Point}, then no way to compare for equality with it exists. |
| 154 | +Now, we could return \pythonil{False} in this case, which would be fine as well. |
| 155 | +Returning \pythonilIdx{NotImplemented} will give us the same result in comparisons with objects of other types~(like~\pythonil{5}). |
| 156 | +However, it keeps an avenue open for other programmers to design new classes which support comparison with our \pythonil{Point} instances in a consistent way. |
138 | 157 |
|
139 | 158 | \Cref{lst:dunder:point_with_dunder_user} is the same as \cref{lst:dunder:point_user_2}, but now uses this new variant of our class \pythonil{Point}.
|
140 |
| -As you can see in \cref{exec:dunder:point_with_dunder_user}, its output now matches much better to what one would expect. |
| 159 | +As you can see in \cref{exec:dunder:point_with_dunder_user}, its output now matches much better to what one would expect.% |
141 | 160 | \endhsection%
|
142 | 161 | %
|
143 | 162 | \endhsection%
|
0 commit comments