[Python-Dev] Re: PEP 326 now online

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 (Py_EnterRecursiveCall(" 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 "findmin_Max" 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)?

 - Josiah




More information about the Python-Dev mailing list