Skip to content

Commit 1e030df

Browse files
committed
improved __eq__ explanation and implementation
1 parent 80927bf commit 1e030df

File tree

2 files changed

+33
-7
lines changed

2 files changed

+33
-7
lines changed

bibliography/bibliography.bib

+9-2
Original file line numberDiff line numberDiff line change
@@ -2249,15 +2249,22 @@ @inbook{PSF2024ACO
22492249
urldate = {2024-10-09},
22502250
}
22512251

2252+
@inbook{PSF2024BIC,
2253+
title = {Built\nobreakdashes-in Constants},
2254+
xdata = {PSF2024TPSL},
2255+
url = {https://docs.python.org/3/library/constants.html},
2256+
urldate = {2024-12-09},
2257+
}
2258+
22522259
@inbook{PSF2024BIE,
2253-
title = {Built-in \pythonilsIdx{Exception}},
2260+
title = {Built\nobreakdashes-in \pythonilsIdx{Exception}},
22542261
xdata = {PSF2024TPSL},
22552262
url = {https://docs.python.org/3/library/exceptions.html},
22562263
urldate = {2024-10-29},
22572264
}
22582265

22592266
@inbook{PSF2024BIT,
2260-
title = {Built-in Types},
2267+
title = {Built\nobreakdashes-in Types},
22612268
xdata = {PSF2024TPSL},
22622269
url = {https://docs.python.org/3/library/stdtypes.html},
22632270
urldate = {2024-08-22},

text/main/classes/dunder/dunder.tex

+24-5
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,14 @@
119119
}. %
120120
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}.
121121

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+
122130
\gitPython{\programmingWithPythonCodeRepo}{09_dunder/point_with_dunder.py}{--args format}{dunder:point_with_dunder}{%
123131
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.}%
124132
%
@@ -129,15 +137,26 @@
129137
The concise string representation returned by \pythonilIdx{\_\_str\_\_}\pythonIdx{dunder!\_\_str\_\_} will just be the point coordinates in parentheses.
130138
This offers all the information needed at a glance, but it could be mistaken with a tuple as string.
131139
Therefore, the canonical string representation produced by \pythonilIdx{\_\_repr\_\_}\pythonIdx{dunder!\_\_repr\_\_} will return a string of the shape~\pythonil{"Point(x, y)"}.
140+
132141
Finally, the \pythonilIdx{\_\_eq\_\_}\pythonIdx{dunder!\_\_eq\_\_} method will first check if the \pythonil{other} object is an instance of \pythonil{Point}.
133142
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.
138157

139158
\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.%
141160
\endhsection%
142161
%
143162
\endhsection%

0 commit comments

Comments
 (0)