By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
458,107 Members | 1,221 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 458,107 IT Pros & Developers. It's quick & easy.

Why does min(A,B) behave different for lists and for classes?

P: n/a
Trying to understand the outcome of the recent
thread (called later reference thread):

"Speed quirk: redundant line gives six-fold speedup"

I have put following piece of Python code together:

class PythonObject_class:
pass
PythonObject_class_instanceA = PythonObject_class()
PythonObject_class_instanceB = PythonObject_class()
PythonObject_list_instanceA = [1]
PythonObject_list_instanceB = [1]

print "min(A,B) is A: "
print "in case of classes as parameter: " +
str(min(PythonObject_class_instanceA, PythonObject_class_instanceB) is
PythonObject_class_instanceA)
print "in case of lists as parameter: " +
str(min(PythonObject_list_instanceA, PythonObject_list_instanceB) is
PythonObject_list_instanceA)
print "min(B,A) is A: "
print "in case of classes as parameter: " +
str(min(PythonObject_class_instanceB,
PythonObject_class_instanceA) is PythonObject_class_instanceA)
print "in case of lists as parameter: " +
str(min(PythonObject_list_instanceB,
PythonObject_list_instanceA) is PythonObject_list_instanceA)

getting as output:

min(A,B) is A:
in case of classes as parameter: True
in case of lists as parameter: True
min(B,A) is A:
in case of classes as parameter: True
in case of lists as parameter: False

Is there any deeper reason I don't understand
explaining why does min(A,B) behave different
for classes than for lists?
It makes for me currently not much sense how it
behaves for classes, because the result is according
to the postings in the above mentioned reference
thread nondeterministic.

Claudio
Aug 26 '05 #1
Share this Question
Share on Google+
3 Replies


P: n/a
Claudio Grondi wrote:
Is there any deeper reason I don't understand
explaining why does min(A,B) behave different
for classes than for lists?


Yes, the sort order for lists is determined by their contents. With
your example, the lists have identical contents, so min() returns the
first minimum value encountered which is A for min(A,B) and B for
min(B,A).

For instances, the sort order is determined by custom __cmp__ or rich
comparision methods. In the absence of those, the default ordering is
determined by the object's id. In your example, the default is used
and either object may be returned as the minimum depending on which
object id is a higher number (that is an implementation and state
dependent). Since the two objects have unique ids, min() will
consistently find one to be lower than the other irrespective of
argument order, if min(A,B) is A, then min(B,A) will also be A.

The best way to develop your understanding here is view the object ids
for the instances and experiment with the results of A<B, A<=B, A==B,
etc.

Then write a simple, pure python version of min() that returns the
first occurence of the lowest valued element. Trace through its
execution and all will become clear.
Raymond

Aug 26 '05 #2

P: n/a
Thanks to Raymond for his reply.

If I understand him right, there is no problem with
min() as such, but with the definition of the class, which
when used in min() should define at least __cmp__().

I have attached code with another
class PythonObject_classWithDefined__cmp__:
where the behaviour of min() is like I would
expect it.

Using classes without defined __cmp__ in comparison
operations violates the directive:
"Explicit is better than implicit"
and is just to be considered bad programming
style or to name it more directly, just a way of
obfuscating code, right?

The still open question for me then is:
Why does min() not raise an error in case
there is no comparison function definition
for the feeded objects available?

Claudio

ATTACHMENT:

class PythonObject_classWithDefined__cmp__:
def __init__(self, value = 1):
self.value = value
#:def
def __cmp__(self, otherInstance):
if ( self.value < otherInstance.value ):
return -1
elif(self.value == otherInstance.value ):
return 0
else:
return 1
#:if/else
#:def
#:class

PythonObject_classWithDefined__cmp__instanceA =
PythonObject_classWithDefined__cmp__()
PythonObject_classWithDefined__cmp__instanceB =
PythonObject_classWithDefined__cmp__()
print "min(A,B) is A: "
print "in case of classes with defined __cmp__() as parameter: " +
str(min(PythonObject_classWithDefined__cmp__instan ceA,
PythonObject_classWithDefined__cmp__instanceB) is
PythonObject_classWithDefined__cmp__instanceA)
print "min(B,A) is A: "
print "in case of classes with defined __cmp__() as parameter: " +
str(min(PythonObject_classWithDefined__cmp__instan ceB,
PythonObject_classWithDefined__cmp__instanceA) is
PythonObject_classWithDefined__cmp__instanceA)

outputs:

min(A,B) is A:
in case of classes with defined __cmp__() as parameter: True
min(B,A) is A:
in case of classes with defined __cmp__() as parameter: False
"Raymond Hettinger" <py****@rcn.com> schrieb im Newsbeitrag
news:11**********************@o13g2000cwo.googlegr oups.com...
Claudio Grondi wrote:
Is there any deeper reason I don't understand
explaining why does min(A,B) behave different
for classes than for lists?


Yes, the sort order for lists is determined by their contents. With
your example, the lists have identical contents, so min() returns the
first minimum value encountered which is A for min(A,B) and B for
min(B,A).

For instances, the sort order is determined by custom __cmp__ or rich
comparision methods. In the absence of those, the default ordering is
determined by the object's id. In your example, the default is used
and either object may be returned as the minimum depending on which
object id is a higher number (that is an implementation and state
dependent). Since the two objects have unique ids, min() will
consistently find one to be lower than the other irrespective of
argument order, if min(A,B) is A, then min(B,A) will also be A.

The best way to develop your understanding here is view the object ids
for the instances and experiment with the results of A<B, A<=B, A==B,
etc.

Then write a simple, pure python version of min() that returns the
first occurence of the lowest valued element. Trace through its
execution and all will become clear.
Raymond


Aug 26 '05 #3

P: n/a
[Claudio Grondi]
The still open question for me then is:
Why does min() not raise an error in case
there is no comparison function definition
for the feeded objects available?


Actually, there is a comparison function for
class instances. Unfortunately, the default
method is not very useful in your case. It
works a bit like this:

def __cmp__(self, other):
return cmp(id(self), id(other))

This is mildly useful as it allows distinct
objects to have an ordering relation.
Raymond

Aug 26 '05 #4

This discussion thread is closed

Replies have been disabled for this discussion.