Velocity Reviews > Comparison of functions

# Comparison of functions

Steven D'Aprano
Guest
Posts: n/a

 07-30-2005
Playing around with comparisons of functions (don't ask), I discovered an
interesting bit of unintuitive behaviour:

>>> (lambda y: y) < (lambda y: y)

False

Do the comparison again and things become even more bizarre:

>>> (lambda y: y) < (lambda y: y)

True
>>> (lambda y: y) < (lambda y: y)

False

This behaviour should be easy for experienced Pythonisters to answer, but
will probably confuse beginners greatly.

For the benefit of beginners, imagine we expand the first line into two,
and commit what some people call an abuse of lambdas: we bind them to
names.

>>> a = lambda y: y
>>> b = lambda y: y
>>> a

<function <lambda> at 0xf70598ec>
>>> b

<function <lambda> at 0xf7059844>

a and b are now bound to two objects, each of which is an anonymous
function that just happens to do the same thing. But each time you create
a lambda function, you get a different object at some unpredictable
location in memory.

This is where my level of Python knowledge fails me. I don't understand
how Python is comparing the two objects since neither a nor b have any
rich comparison methods or even the old-style __cmp__ method.

>>> a < b

False

So I'm puzzled about how Python compares the two.

If we compare a and b again, we will always get the same answer. But if we
create a new pair of anonymous functions with lambda, and compare them, it
is the luck of the draw each time whether the first compares bigger or
smaller than the second.

--
Steven.

Peter Hansen
Guest
Posts: n/a

 07-30-2005
Steven D'Aprano wrote:
> Playing around with comparisons of functions (don't ask), I discovered an
> interesting bit of unintuitive behaviour:
>
>>>>(lambda y: y) < (lambda y: y)

> False
>
> Do the comparison again and things become even more bizarre:
>
>>>>(lambda y: y) < (lambda y: y)

> True
>
>>>>(lambda y: y) < (lambda y: y)

> False
>
> This behaviour should be easy for experienced Pythonisters to answer, but
> will probably confuse beginners greatly.

Beginners should not be comparing lambdas.

Neither should you.

-Peter

tiissa
Guest
Posts: n/a

 07-30-2005
Steven D'Aprano wrote:
> Playing around with comparisons of functions (don't ask), I discovered an
> interesting bit of unintuitive behaviour:
>
>>>>a = lambda y: y
>>>>b = lambda y: y
>>>>a

> <function <lambda> at 0xf70598ec>
>>>>b

> <function <lambda> at 0xf7059844>
>>>>a < b

> False
>
> So I'm puzzled about how Python compares the two.

Seems to me the object addresses are compared in this case. But I'm too
lazy to check it in the source.

However, the doc [1] warns you about such comparisons:
"""Most other types compare unequal unless they are the same object; the
choice whether one object is considered smaller or larger than another
one is made arbitrarily but consistently within one execution of a
program."""

[1] http://docs.python.org/ref/comparisons.html

Guest
Posts: n/a

 07-30-2005
Steven D'Aprano ha scritto:
> On Sat, 30 Jul 2005 08:13:26 -0400, Peter Hansen wrote:
>
>
>>Beginners should not be comparing lambdas.
>>
>>Neither should you.

>
>
> Actually, yes I should, because I'm trying to make sense of the mess that
> is Python's handling of comparisons. At least two difference senses of
> comparisons is jammed into one, leading to such such warts as these:
>
>
>>>>L = []
>>>>L.sort() # we can sort lists
>>>>L.append(1+1j)
>>>>L.sort() # even if they include a complex number
>>>>L.append(1)
>>>>L.sort() # but not any more

>
> Traceback (most recent call last):
> File "<stdin>", line 1, in ?
> TypeError: cannot compare complex numbers using <, <=, >, >=
>
> Um, I didn't ask to compare complex numbers using comparison operators. I
> asked to sort a list. And please don't tell me that that sorting is
> implemented with comparison operators. That just means that the
> implementation is confusing numeric ordering with sort order.
>
> Then there is this:
>
>
>>>>1 > 0

>
> True
>
>>>>1+0j == 1

>
> True
>
>>>>1+0j == 1 > 0

>
> True
>
>>>>1+0j > 0

>
> Traceback (most recent call last):
> File "<stdin>", line 1, in ?
> TypeError: cannot compare complex numbers using <, <=, >, >=
>
> I applaud that Python has got rich comparisons for those who need them.
> But by confusing the question "which comes first in a sorted list?" with
> "which is larger?", you get all sorts of warts like being unable to sort
> lists with some objects, while being able to make meaningless
> comparisons like ''.join >= [].append.
>
> I'm not sure what the solution to this ugly state of affairs is. I'm not
> even sure if there is a solution. But I'm willing to make a good effort to
> *look*, and even though you were joking, I don't appreciate being told
> not to.

As far as I recall from Math Analysis, which I studied two months ago,
you can't sort complex numbers. It makes no sense. The reason being
(reading from my book), it's not possible to define an order that
preserves the properties of arithmetical operations on complex numbers.
So you can't order them, and you can't compare them.

--
The Inside Out: http://moranar.com.ar
MSN: http://www.velocityreviews.com/forums/(E-Mail Removed)
ICQ: 4410132

Guest
Posts: n/a

 07-30-2005

> As far as I recall from Math Analysis, which I studied two months ago,
> you can't sort complex numbers. It makes no sense. The reason being
> (reading from my book), it's not possible to define an order that
> preserves the properties of arithmetical operations on complex numbers.
> So you can't order them, and you can't compare them.
>

Sorry, that should have been "you can't sort them, and you can't compare
them with greater than, lesser than, etc. Of course, using == will work.

But tell me, how do you think sort works if not with <, >, ==, <= and >=
? I'm really interested.

--
The Inside Out: http://moranar.com.ar
MSN: (E-Mail Removed)
ICQ: 4410132

Reinhold Birkenfeld
Guest
Posts: n/a

 07-30-2005
Steven D'Aprano wrote:
> On Sat, 30 Jul 2005 08:13:26 -0400, Peter Hansen wrote:
>
>> Beginners should not be comparing lambdas.
>>
>> Neither should you.

>
> Actually, yes I should, because I'm trying to make sense of the mess that
> is Python's handling of comparisons. At least two difference senses of
> comparisons is jammed into one, leading to such such warts as these:
>
>>>> L = []
>>>> L.sort() # we can sort lists
>>>> L.append(1+1j)
>>>> L.sort() # even if they include a complex number
>>>> L.append(1)
>>>> L.sort() # but not any more

> Traceback (most recent call last):
> File "<stdin>", line 1, in ?
> TypeError: cannot compare complex numbers using <, <=, >, >=
>
> Um, I didn't ask to compare complex numbers using comparison operators. I
> asked to sort a list. And please don't tell me that that sorting is
> implemented with comparison operators. That just means that the
> implementation is confusing numeric ordering with sort order.

Sorting is implemented with comparison operators. How should it be otherwise?
Would you prefer a __sort__ method to specify sort order?

And how would you sort a list of complex numbers?

> Then there is this:
>
>>>> 1 > 0

> True

Okay.

>>>> 1+0j == 1

> True

Okay.

>>>> 1+0j == 1 > 0

> True

(1+0j == 1) yields True, which is comparable to 0.

>>>> 1+0j > 0

> Traceback (most recent call last):
> File "<stdin>", line 1, in ?
> TypeError: cannot compare complex numbers using <, <=, >, >=

But complex numbers are not greater or littler than others. You can't order them,
not on a one-dimensional scale.

> I applaud that Python has got rich comparisons for those who need them.
> But by confusing the question "which comes first in a sorted list?" with
> "which is larger?", you get all sorts of warts like being unable to sort
> lists with some objects, while being able to make meaningless
> comparisons like ''.join >= [].append.

That's a wart indeed, and intended to be removed for 3.0, if I'm informed correctly.

Reinhold

Steven D'Aprano
Guest
Posts: n/a

 07-30-2005
On Sat, 30 Jul 2005 08:13:26 -0400, Peter Hansen wrote:

> Beginners should not be comparing lambdas.
>
> Neither should you.

Actually, yes I should, because I'm trying to make sense of the mess that
is Python's handling of comparisons. At least two difference senses of
comparisons is jammed into one, leading to such such warts as these:

>>> L = []
>>> L.sort() # we can sort lists
>>> L.append(1+1j)
>>> L.sort() # even if they include a complex number
>>> L.append(1)
>>> L.sort() # but not any more

Traceback (most recent call last):
File "<stdin>", line 1, in ?
TypeError: cannot compare complex numbers using <, <=, >, >=

Um, I didn't ask to compare complex numbers using comparison operators. I
asked to sort a list. And please don't tell me that that sorting is
implemented with comparison operators. That just means that the
implementation is confusing numeric ordering with sort order.

Then there is this:

>>> 1 > 0

True
>>> 1+0j == 1

True
>>> 1+0j == 1 > 0

True
>>> 1+0j > 0

Traceback (most recent call last):
File "<stdin>", line 1, in ?
TypeError: cannot compare complex numbers using <, <=, >, >=

I applaud that Python has got rich comparisons for those who need them.
But by confusing the question "which comes first in a sorted list?" with
"which is larger?", you get all sorts of warts like being unable to sort
lists with some objects, while being able to make meaningless
comparisons like ''.join >= [].append.

I'm not sure what the solution to this ugly state of affairs is. I'm not
even sure if there is a solution. But I'm willing to make a good effort to
*look*, and even though you were joking, I don't appreciate being told
not to.

--
Steven.

Steven D'Aprano
Guest
Posts: n/a

 07-30-2005
On Sat, 30 Jul 2005 14:20:50 +0200, tiissa wrote:

> Steven D'Aprano wrote:
>> Playing around with comparisons of functions (don't ask), I discovered an
>> interesting bit of unintuitive behaviour:
>>
>>>>>a = lambda y: y
>>>>>b = lambda y: y
>>>>>a

>> <function <lambda> at 0xf70598ec>
>>>>>b

>> <function <lambda> at 0xf7059844>
>>>>>a < b

>> False
>>
>> So I'm puzzled about how Python compares the two.

>
> Seems to me the object addresses are compared in this case. But I'm too
> lazy to check it in the source.

Strangely enough, I'm lazy enough to not check the source too

Actually, more to the point, I don't read C, so even if I did check the
source, I wouldn't know what it was trying to tell me.

> However, the doc [1] warns you about such comparisons: """Most other
> types compare unequal unless they are the same object; the choice
> whether one object is considered smaller or larger than another one is
> made arbitrarily but consistently within one execution of a program."""

I am aware of that. That's a wart.

--
Steven.

Georg Neis
Guest
Posts: n/a

 07-30-2005
* Reinhold Birkenfeld <(E-Mail Removed)> wrote:
> Steven D'Aprano wrote:
>>>>> 1+0j == 1 > 0

>> True

>
> (1+0j == 1) yields True, which is comparable to 0.

"a == b > c" is equivalent to "a == b and b > c":

>>> 1 == 1+0j > 0

Traceback (most recent call last):
File "<stdin>", line 1, in ?
TypeError: cannot compare complex numbers using <, <=, >, >=

Guest
Posts: n/a

 07-30-2005
Steven D'Aprano ha scritto:

> It was easy. I never once asked myself whether some complex number was
> greater or less than another, I just asked "which one comes first in a
> lexicographic sort?"
>
> The two questions are NOT the same, and it is an ugliness in an otherwise
> beautiful language that Python treats them as the same.
>
> Mathematically, 1 == 1.0 == 1+0j but in the dictionary "1" should sort
> before "1.0" which sorts before "1.0+0.0j".

Because, of course, when I sort numbers the first thing I think of is
looking at the ascii table... Here I was, thinking maths was useful.
Sorting numbers "lexicographically" might make sense to you, but it's
totally unintuitive to me. For example, why or how would I guess that
"3-3j" is bigger (or smaller) than "3+3j"?

You'll still want to sort complex numbers lexicographically. It'll still
have no meaning whatsoever, so you might as well leave the list
unsorted. You might think you sorted something. 100? 200? years of maths
say you didn't.

--
The Inside Out: http://moranar.com.ar
MSN: (E-Mail Removed)
ICQ: 4410132