comparison with None

T

Terry Reedy

| >>> None >= 0
| False
| >>> None <= 0
| True
|
| Explanation appreciated.

Should be in the reference manual section on comparisons.
 
S

Steven Howe

Alan said:
True

Explanation appreciated.

Thanks,
Alan Isaac
I've read and found that 'None' comparisons is not always a good idea.
Better to:
from types import NoneType

x = None
if type( x ) == NoneType:
# true
< code >
else:
# false; do something else.
< more code >

Steven Howe
 
P

Paul McGuire

I've read and found that 'None' comparisons is not always a good idea.
Better to:
from types import NoneType

x = None
if type( x ) == NoneType:
# true
< code >
else:
# false; do something else.
< more code >

Steven Howe

None is a singleton - there is but one None and no other. The only
comparisons that make sense with None are "is" or "is not". type(x)
== NoneType is unnecessary, x is None is sufficient.
False

-- Paul
 
B

brzrkr0

I've read and found that 'None' comparisons is not always a good idea.
Better to:
from types import NoneType

x = None
if type( x ) == NoneType:
# true
< code >
else:
# false; do something else.
< more code >

Steven Howe

Is that any better than this?

if x is None:
# do something
else:
# do something else
 
M

Michael Hoffman

Is that any better than this?

if x is None:
# do something
else:
# do something else

To the contrary, it's not as good. "if x is None" is much clearer, and
probably faster.
 
G

Gary Herron

Alan said:
True

Explanation appreciated.

Thanks,
Alan Isaac
So that we can sort lists of objects, even when the objects of are
different types, Python guarantees to supply a unique and consistent
ordering of any two objects. The definition of Python does not specify
what that ordering is -- that's implementation dependent -- but any two
objects of any two types *do* have an ordering and that ordering will
always be the same.

So in your implementation None is less than 0 (and probably less than
any integer). Given that, your two observations above are consistent.

Gary Herron
 
R

Robert Kern

Steven said:
I've read and found that 'None' comparisons is not always a good idea.
Better to:
from types import NoneType

x = None
if type( x ) == NoneType:
# true
< code >
else:
# false; do something else.
< more code >

The recommended idiom is to test for "x is None".

--
Robert Kern

"I have come to believe that the whole world is an enigma, a harmless enigma
that is made terrible by our own mad attempt to interpret it as though it had
an underlying truth."
-- Umberto Eco
 
A

Alan Isaac

Terry Reedy said:
Should be in the reference manual section on comparisons.

Only to this extent:
http://www.python.org/doc/2.4/ref/comparisons.html

objects of different types always compare unequal, and are ordered
consistently but arbitrarily.

(This unusual definition of comparison was used to simplify the
definition of operations like sorting and the in and not in
operators.
In the future, the comparison rules for objects of different types
are
likely to change.)

... 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.

This does not provide a direct answer to "why" None comparisons.
(As far as I can tell, None is less than any object.)

However, Gary Herron's explanation makes sense: this provides a stable
sort when None is involved, and meets the criterion that objects of
different types must always compare unequal. However this would also
be true if None always compared greater than any object, and the current
behavior does not seem to be guaranteed.

Is that about right?

Cheers,
Alan Isaac
 
S

Steven D'Aprano

I've read and found that 'None' comparisons is not always a good idea.

You're probably thinking of testing against None with equality:

if x == None: do_something()

That can go wrong if x is a class that has an overly-broad concept of
equality, e.g.:

class FalseKlass:
def __eq__(self, other):
# equal to anything that is False
return not other

Better to:
from types import NoneType

x = None
if type( x ) == NoneType:
# true
< code >
else:
# false; do something else.
< more code >


Not necessary. Since None is a guaranteed singleton, the only test you
need to make is "if x is None: ...".

But if you wanted to do extra work unnecessarily, a less unnecessary
amount of extra work would be:

if type(x) == type(None): ...

You don't need to look up the type of None in the types module when you
can easily get it from the type() function.
 
B

Bruno Desthuilliers

Steven Howe a écrit :
(snip)
I've read and found that 'None' comparisons is not always a good idea.
Better to:
from types import NoneType

x = None
if type( x ) == NoneType:
# true
< code >
else:
# false; do something else.
< more code >

Actually, None is garanteed to be a singleton, so the idiomatic way is
to use an identity test:

if x is None:
# code here

But this doesn't answer the OP...

HTH
 
A

Alex Martelli

Alan Isaac said:
currently documented behavior:
"objects of different types always compare unequal".

Where is that documented? URL please?
(<type 'float'>, <type 'int'>)

here, just as an example, are two objects of different types that
compare equal; therefore that "documented behavior" is flat wrong and
needs to be fixed.


Alex
 
A

Alex Martelli

Steven D'Aprano said:
But if you wanted to do extra work unnecessarily, a less unnecessary
amount of extra work would be:

if type(x) == type(None): ...

Of course, like the original poster's proposal, this CAN be faked out
(while the 'is' test cannot, one more weird reason why it's better):
.... def __eq__(self, other): return True
.... True


(warning to all innocent bystanders: don't try this at home, kids!-)


Alex
 
T

Tommy Grav

Where is that documented? URL please?

(<type 'float'>, <type 'int'>)

Isn't this an example of numerical comparison (= or !=) versus
object comparison (is or is not). I think the documentation needs
to state that there is a difference between the two types.

Cheers
Tommy
 
A

Alex Martelli

Tommy Grav said:
Isn't this an example of numerical comparison (= or !=) versus
object comparison (is or is not). I think the documentation needs
to state that there is a difference between the two types.

Operator == (TWO equal signs, not just one: that would be an assignment
instead) can be applied to arbitrary objects, not just numbers, just
like operator 'is'.
(<type 'unicode'>, <type 'str'>)

See, it's not a question of numbers versus other things: the
distinction, rather, is between comparison of the values of objects
(which can perfectly well be equal even for objects of different types)
versus checking object identity (and since an object only has one type
at a time, it can't be "the same object" as one with a different type).
Why do you think the Python docs don't draw the difference between '=='
(equality) and 'is' (identity)?

I'm still interested to know where that erroneous quote from Alan Isaac
comes from, because if it's in Python's docs, it can be fixed.


Alex
 
G

Gabriel Genellina

I'm still interested to know where that erroneous quote from Alan Isaac
comes from, because if it's in Python's docs, it can be fixed.

It was a partial quote, that's why it appeared to be wrong:

Library reference, 3.3 Comparisons

"Objects of different types, except different numeric types and different
string types, never compare equal; such objects are ordered consistently
but arbitrarily."

Reference Manual, 5.9 Comparisons

"The objects need not have the same type. If both are numbers, they are
converted to a common type. Otherwise, objects of different types always
compare unequal, and are ordered consistently but arbitrarily."

(Apart from the latter not menctioning string types too, looks good to me).
 
A

Alex Martelli

Gabriel Genellina said:
It was a partial quote, that's why it appeared to be wrong:

Library reference, 3.3 Comparisons

"Objects of different types, except different numeric types and different
string types, never compare equal; such objects are ordered consistently
but arbitrarily."

Reference Manual, 5.9 Comparisons

"The objects need not have the same type. If both are numbers, they are
converted to a common type. Otherwise, objects of different types always
compare unequal, and are ordered consistently but arbitrarily."

(Apart from the latter not menctioning string types too, looks good to me).

Right. However, it might be worth underscoring that this applies to
_built-in_ types, and user-defined types are free to implement different
comparison semantics, although that should be done with care and good
taste; for example, one might have a collection type defining __eq__ to
mean "the same set of items as the other [iterable] operand in any
order", though that might cause weird behavior such as a==b but b!=a
(unfortunately there's no __req__, and __coerce__ is not involved in
comparisons either).

Still, not a major concern -- numbers and strings _do_ exhaust a vast
majority of the use cases for object of different types comparing equal.


Alex
 
G

Gabriel Genellina

Gabriel Genellina said:
Reference Manual, 5.9 Comparisons

"The objects need not have the same type. If both are numbers, they are
converted to a common type. Otherwise, objects of different types always
compare unequal, and are ordered consistently but arbitrarily."

(Apart from the latter not menctioning string types too, looks good to
me).

Right. However, it might be worth underscoring that this applies to
_built-in_ types, and user-defined types are free to implement different
comparison semantics, although that should be done with care and good
taste; for example, one might have a collection type defining __eq__ to
mean "the same set of items as the other [iterable] operand in any
order", though that might cause weird behavior such as a==b but b!=a
(unfortunately there's no __req__, and __coerce__ is not involved in
comparisons either).

BTW, I think that the relationship between __eq__ and __hash__ (a==b =>
hash(a)==hash(b), when hashable) should be more clearly stated too. I
almost got insane some time ago because of a faulty Rational numbers
implementation where hash(1/2)!=hash(2/4) (so dictionaries didn't work at
all).
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,270
Messages
2,571,101
Members
48,773
Latest member
Kaybee

Latest Threads

Top