> Here are my comments on PEP 207. (I've also gone back and read most > of the 1998 discussion. What a tedious, in terms of time, but > enlightening, in terms of content, discussion that was.) > > | - New function: > | > | PyObject *PyObject_RichCompare(PyObject *, PyObject *, enum cmp_op) > | > | This performs the requested rich comparison, returning a Python > | object or raising an exception. The 3rd argument must be one of > | LT, LE, EQ, NE, GT or GE. > > I'd much prefer '<', '<=', '=', etc. to LT, LE, EQ, etc. This is only at the C level. Having to do a string compare is too slow. Since some of these are multi-character symbols, a character constant doesn't suffice (multi-character character constants are not portable). > | Classes > | > | - Classes can define new special methods __lt__, __le__, __gt__, > | __ge__, __eq__, __ne__ to override the corresponding operators. > | (You gotta love the Fortran heritage.) If a class overrides > | __cmp__ as well, it is only used by PyObject_Compare(). > > Likewise, I'd prefer __less__, __lessequal__, __equal__, etc. to > __lt__, __le__, __eq__, etc. I'm not keen on the FORTRAN derived > symbolism. I also find it contrary to Python's heritage of being > clear and concise. I don't mind typing __lessequal__ (or > __less_equal__) once per class for the additional clarity. I don't care about Fortran, but you just showed why I think the short operator names are better: there's less guessing or disagreement about how they are to be spelled. E.g. should it be __lessthan__ or __less_than__ or __less__? > | - Should we even bother upgrading the existing types? > > Isn't this question partly related to the coercion issue and which > type of comparison takes precedence? And if so, then I would think > the answer would be 'yes'. It wouldn't make much of a difference -- comparisons between different types numbers would get the same outcome either way. > Or better still see below my suggestion of > adding poor and rich comparison operators along with matrix-type > operators. > > > - If so, how should comparisons on container types be defined? > Suppose we have a list whose items define rich comparisons. How > should the itemwise comparisons be done? For example: > > def __lt__(a, b): # a<b for lists > for i in range(min(len(a), len(b))): > ai, bi = a[i], b[i] > if ai < bi: return 1 > if ai == bi: continue > if ai > bi: return 0 > raise TypeError, "incomparable item types" > return len(a) < len(b) > > This uses the same sequence of comparisons as cmp(), so it may > as well use cmp() instead: > > def __lt__(a, b): # a<b for lists > for i in range(min(len(a), len(b))): > c = cmp(a[i], b[i]) > if c < 0: return 1 > if c == 0: continue > if c > 0: return 0 > assert 0 # unreachable > return len(a) < len(b) > > And now there's not really a reason to change lists to rich > comparisons. > > I don't understand this example. If a[i] and b[i] define rich > comparisons, then 'a[i] < b[i]' is likely to return a non-boolean > value. Yet the 'if' statement expects a boolean value. I don't see > how the above example will work. Sorry. I was thinking of list items that contain objects that respond to the new overloading protocol, but still return Boolean outcomes. My conclusion is that __cmp__ is just as well. > This example also makes me think that the proposals for new operators > (ie. PEP 211 and 225) are a good idea. The discussion of rich > comparisons in 1998 also lends some support to this. I can see many > uses for two types of comparison operators (as well as the proposed > matrix-type operators), one set for poor or boolean comparisons and > one for rich or non-boolean comparisons. For example, numeric arrays > can define both. Rich comparison operators would return an array of > boolean values, while poor comparison operators return a boolean value > by performing an implied 'and.reduce' operation. These operators > provide clarity and conciseness, without much change to current Python > behavior. Maybe. That can still be decided later. Right now, adding operators is not on the table for 2.1 (if only because there are two conflicting PEPs); adding rich comparisons *is* on the table because it doesn't change the parser (and because the rich comparisons idea was already pretty much worked out two years ago). --Guido van Rossum (home page: http://www.python.org/~guido/)
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4