[Python-Dev] Re: PEP 326 now online (original) (raw)

Josiah Carlson jcarlson at uci.edu
Mon Jan 26 19:47:43 EST 2004


[...]

My suggestion is to not introduce these objects at all, and if they're going to be introduced, there should be internal support for them in the interpreter, or they're meaningless. Every object with a custom cmp method would have to take care not to be greater than your objects.

Interpretation: You are -1 on the PEP in general. If it does get introduced, then you are +1 on there being a special case in the interpreter for when Min or Max are in the comparison.

If given the proper values for PyMinObject and PyMaxObject (quite the large 'if given'), it is an 5 line modification to PyObject_Compare in object.c:

int PyObject_Compare(PyObject *v, PyObject *w) { PyTypeObject *vtp; int result;

if (v == NULL || w == NULL) {
    PyErr_BadInternalCall();
    return -1;
}
if (v == w)
    return 0;
vtp = v->ob_type;

if (v == PyMinObject || w == PyMaxObject) return -1; else if (v == PyMaxObject || w == PyMinObject) return 1; else if (PyEnterRecursiveCall(" in cmp")) return -1; result = do_cmp(v, w); Py_LeaveRecursiveCall(); return result < 0 ? -1 : result; }

Unfortunately the above seems to imply that Min and Max would need to be builtins (I may be wrong here, please correct me if I am), and new builtins have been frowned upon by most everyone since the beginning.

[...]

> Take a look at the first few examples in the 'Max Examples' section of > the PEP: http://www.python.org/peps/pep-0326.html#max-examples > Notice the reduction in code from using only numbers, to using None, to > using Max? Notice how each implementation got clearer? That is what > the PEP is about, making code clearer.

Comments about the "Max Examples": - If the objects in the sequence implement their own cmp operator, you can't be sure your example will work. That turns these structures (call them as you want) into something useless.

Those who want to use Max and/or Min, and want to implement their own cmp operator - which uses non-standard behavior when comparing against Max and/or Min - may have to deal with special cases involving Max and/or Min.

This makes sense because it is the same deal with any value or object you want to result in non-standard behavior. If people want a special case, then they must write the special case.

- "Max" is a possible return from this function. It means the code using your "findminMax" will have to "if foo == Max" somewhere, so it kills your argument of less code as well.

No, it doesn't. min(a, Max) will always return a.

I should have included a test for empty sequences as an argument in order to differentiate between empty sequences and sequences that have (0, None, Max) as their actual minimum values (in the related code snippets).

This results in the simplification of the (0, None) examples into one, but introduces an index variable and sequence lookups for the general case:

def findmin_General(seq): if not len(seq): raise TypeError("Sequence is empty") cur = seq[0] for i in xrange(1, len(seq)): cur = min(seq[i], cur) return cur

def findmin_Max(seq): if not len(seq): raise TypeError("Sequence is empty") cur = Max for obj in seq: cur = min(obj, cur) return cur

Now they both have the same number of lines, but I find the second one a bit clearer due its lack of sequence indexing.

[...] > An even better question would be, "How would two objects with cmp > react?" Checking a few examples, it is whoever is on the left side of > the comparison operator.

Exactly. That's the point. Your "Top" value is not really "Top", unless every object with custom comparison methods take care about it.

Certainly anyone who wants to use Max/Min may have to take care to use it properly. How is this any different from the way we program with any other special values?

Just to point things out, when comparing two standard python data types (int, float, None, dict, list, tuple, str), cmp calls the left data type's cmp operator. When comparing an object that is not a standard python data type to anything else, cmp calls the leftmost non-standard object's existant cmp operator. The described behavior looks to be consistant with current CVS for object.c, in which the various cmp functions are defined.

Perhaps this behavior should be documented in the customization documentation.

[...]

> As stated in the PEP: > "Independent implementations of the Min/Max concept by users desiring > such functionality are not likely to be compatible, and certainly will > produce inconsistent orderings. The following examples seek to show how > inconsistent they can be." (read the PEP for the examples)

Independent implementations are not compatible for the same reason why your implementation is not compatible with the rest of the world. IOW, an indepent implementation would not respect your Max, just like any object with a custom comparison may not respect it.

One of 3 cases would occur:

  1. If Max and Min are in the standard distribution, then the people who use it, would write code that is compatible with it (ok).
  2. Those that have no need for such extreme values will never write code that /could/ be incompatible with it (ok).
  3. Those that don't know about Max/Min, or write their own implementations that overlap with included Python functionality, would not be supported (ok) (I hope the reasons for this are obvious, if they are not, I will clarify).

In any case, the PEP describes the behavior and argues about the creation of the "One True Implementation of the One True Maximum Value and One True Minimum Value", and including it in the standard Python distribution in a reasonable location, with a name that is intuitive.

[...] > The only thing you've "presented" so far is that you think that the > objects are fundamentally useless. On the other hand, no less than 10

Sorry, but you're blind. Review my messages.

My mistake, you've also said that the examples were not good enough, have recently given modifications to the examples that may make them better, and have stated that if Max/Min were to be included, they should have interpreter special cases.

The fact that other people agree with your suggestion doesn't affect my own opinion.

Indeed it doesn't. I was attempting to point out that though you think (in general) that the inclusion of Max and Min values in Python are useless, others (beyond myself) find that they do have uses, and would actually use them.

See this thread (ugly url ahead): http://groups.google.com/groups?hl=en&lr=&ie=UTF-8&safe=off&threadm=mailman.667.1074799564.12720.python-list%40python.org&rnum=1&prev=/groups%3Fhl%3Den%26lr%3D%26ie%3DISO-8859-1%26safe%3Doff%26q%3D326%26btnG%3DGoogle%2BSearch%26meta%3Dgroup%253Dcomp.lang.python.*

[...]

> > Hey, it makes a good case for the PEP; maybe I'll stick it in there if I > have time this afternoon. Thank you for the sugestion.

Ouch! It's getting worse. :-) Put that example in your PEP, please: [...]

I like your optimization of comparisons to None, but the real difference between using None and Max in the node elements are the following:

class DijkstraSPElement_Max: #initialization def cmp(self, other): return cmp(self.distance, other.distance)

class DijkstraSPElement_None: #initialization def cmp(self, other): pair = self.distance, other.distance if None in pair: return cmp(pair)-1 return cmp(*pair)

I'll modify the Dijkstra example to include the objects. Really, they show that for structures that have a comparison key and some additional meta-information attached, Max and Min still win (if only because they don't create and search a two-tuple).

Out of curiosity, why did you use cmp(pair)-1 and not -cmp(*pair)?



More information about the Python-Dev mailing list