Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

easy question on parsing python: "is not None"

20 views
Skip to first unread message

wheres pythonmonks

unread,
Aug 5, 2010, 11:42:06 AM8/5/10
to Python List
How does "x is not None" make any sense? "not x is None" does make sense.

I can only surmise that in this context (preceding is) "not" is not a
unary right-associative operator, therefore:

x is not None === IS_NOTEQ(X, None)

Beside "not in" which seems to work similarly, is there other
syntactical sugar like this that I should be aware of?

W

Roald de Vries

unread,
Aug 5, 2010, 11:56:37 AM8/5/10
to Python List

'not None' first casts None to a bool, and then applies 'not', so 'x
is not None' means 'x is True'.
'not x is None' is the same as 'not (x is None)'

Cheers, Roald

Jean-Michel Pichavant

unread,
Aug 5, 2010, 11:58:54 AM8/5/10
to wheres pythonmonks, Python List
wheres pythonmonks wrote:
> How does "x is not None" make any sense? "not x is None" does make sense.
>
> I can only surmise that in this context (preceding is) "not" is not a
> unary right-associative operator, therefore:
>
> x is not None === IS_NOTEQ(X, None)
>
> Beside "not in" which seems to work similarly, is there other
> syntactical sugar like this that I should be aware of?
>
> W
>
x is not None === not (x is None).

"is not" is an operator, not the combination of 2.


JM

Ben Finney

unread,
Aug 5, 2010, 11:59:01 AM8/5/10
to
wheres pythonmonks <wherespy...@gmail.com> writes:

> How does "x is not None" make any sense?

In two ways: partly from the fact that Python syntax is preferentially
designed to be reasonably readable to a native English reader; and
partly because it makes for more obvious semantics.

‘is not’ is a single operator which makes operator precedence clear, and
also “x is not None” is gramatically good English.

> "not x is None" does make sense.

It unfortunately makes for awkward English, and it also makes for two
separate operators and hence non-obvious operator precedence.

> I can only surmise that in this context (preceding is) "not" is not a
> unary right-associative operator

Rather than surmise, you can read the language reference
<URL:http://docs.python.org/reference/expressions.html#isnot> which
makes clear that ‘is not’ is one operator.

--
\ “I am amazed, O Wall, that you have not collapsed and fallen, |
`\ since you must bear the tedious stupidities of so many |
_o__) scrawlers.” —anonymous graffiti, Pompeii, 79 CE |
Ben Finney

wheres pythonmonks

unread,
Aug 5, 2010, 12:07:53 PM8/5/10
to Roald de Vries, Python List
Well, I am not convinced of the equivalence of not None and true:

>>> not None
True
>>> 3 is True;
False
>>> 3 is not None
True
>>>

P.S. Sorry for the top-post -- is there a way to not do top posts from
gmail? I haven't used usenet since tin.

On Thu, Aug 5, 2010 at 11:56 AM, Roald de Vries <down...@gmail.com> wrote:
> On Aug 5, 2010, at 5:42 PM, wheres pythonmonks wrote:
>>

>> How does "x is not None" make any sense?  "not x is None" does make sense.


>>
>> I can only surmise that in this context (preceding is) "not" is not a

>> unary right-associative operator, therefore:
>>
>> x is not None === IS_NOTEQ(X, None)
>>
>> Beside "not in" which seems to work similarly, is there other
>> syntactical sugar like this that I should be aware of?
>

> 'not None' first casts None to a bool, and then applies 'not', so 'x is not
> None' means 'x is True'.
> 'not x is None' is the same as 'not (x is None)'
>
> Cheers, Roald

> --
> http://mail.python.org/mailman/listinfo/python-list
>

Carey Tilden

unread,
Aug 5, 2010, 12:10:53 PM8/5/10
to Python List
On Thu, Aug 5, 2010 at 8:42 AM, wheres pythonmonks
<wherespy...@gmail.com> wrote:
> How does "x is not None" make any sense?  "not x is None" does make sense.
>
> I can only surmise that in this context (preceding is) "not" is not a
> unary right-associative operator, therefore:
>
> x is not None === IS_NOTEQ(X, None)
>
> Beside "not in" which seems to work similarly, is there other
> syntactical sugar like this that I should be aware of?

In addition to all the other fine responses, you also might want to
take a look at the python grammar [1]. The relevant line is:

comp_op: '<'|'>'|'=='|'>='|'<='|'<>'|'!='|'in'|'not' 'in'|'is'|'is' 'not'

Cheers,
Carey

[1] http://docs.python.org/reference/grammar.html

Chris Rebert

unread,
Aug 5, 2010, 12:11:59 PM8/5/10
to Roald de Vries, Python List
On Thu, Aug 5, 2010 at 8:56 AM, Roald de Vries <down...@gmail.com> wrote:

> On Aug 5, 2010, at 5:42 PM, wheres pythonmonks wrote:
>> How does "x is not None" make any sense?  "not x is None" does make sense.
>>
>> I can only surmise that in this context (preceding is) "not" is not a
>> unary right-associative operator, therefore:
>>
>> x is not None === IS_NOTEQ(X, None)
>>
>> Beside "not in" which seems to work similarly, is there other
>> syntactical sugar like this that I should be aware of?
>
> 'not None' first casts None to a bool, and then applies 'not', so 'x is not
> None' means 'x is True'.

Absolutely incorrect. Read the final paragraph of
http://docs.python.org/reference/expressions.html#notin

Cheers,
Chris
--
http://blog.rebertia.com

Chris Rebert

unread,
Aug 5, 2010, 12:32:47 PM8/5/10
to wheres pythonmonks, Python List
On Thu, Aug 5, 2010 at 8:42 AM, wheres pythonmonks
<wherespy...@gmail.com> wrote:
> How does "x is not None" make any sense?  "not x is None" does make sense.
>
> I can only surmise that in this context (preceding is) "not" is not a
> unary right-associative operator, therefore:
>
> x is not None === IS_NOTEQ(X, None)
>
> Beside "not in" which seems to work similarly, is there other
> syntactical sugar like this that I should be aware of?

It's not quite the same type of sugar as that, but people sometimes
forget that comparisons can be chained:

if x < y <= z:

Same as:

if x < y and y <= z:
# but y is only evaluated once

Cheers,
Chris

Roald de Vries

unread,
Aug 5, 2010, 12:35:53 PM8/5/10
to Python List
On Aug 5, 2010, at 6:11 PM, Chris Rebert wrote:
> On Thu, Aug 5, 2010 at 8:56 AM, Roald de Vries <down...@gmail.com>
> wrote:
>> On Aug 5, 2010, at 5:42 PM, wheres pythonmonks wrote:
>>> How does "x is not None" make any sense? "not x is None" does
>>> make sense.
>>>
>>> I can only surmise that in this context (preceding is) "not" is
>>> not a
>>> unary right-associative operator, therefore:
>>>
>>> x is not None === IS_NOTEQ(X, None)
>>>
>>> Beside "not in" which seems to work similarly, is there other
>>> syntactical sugar like this that I should be aware of?
>>
>> 'not None' first casts None to a bool, and then applies 'not', so
>> 'x is not
>> None' means 'x is True'.
>
> Absolutely incorrect. Read the final paragraph of
> http://docs.python.org/reference/expressions.html#notin

Oops, sorry :$.

Dave Angel

unread,
Aug 5, 2010, 1:03:41 PM8/5/10
to Roald de Vries, Python List
Roald de Vries wrote:
> <div class="moz-text-flowed" style="font-family: -moz-fixed">On Aug 5,
> 2010, at 5:42 PM, wheres pythonmonks wrote:
>> How does "x is not None" make any sense? "not x is None" does make
>> sense.
>>
>> I can only surmise that in this context (preceding is) "not" is not a
>> unary right-associative operator, therefore:
>>
>> x is not None === IS_NOTEQ(X, None)
>>
>> Beside "not in" which seems to work similarly, is there other
>> syntactical sugar like this that I should be aware of?
>
> 'not None' first casts None to a bool, and then applies 'not', so 'x
> is not None' means 'x is True'.
> 'not x is None' is the same as 'not (x is None)'
>
> Cheers, Roald
>
Did you try it?

Python 2.6.4 (r264:75706, Jan 22 2010, 16:41:54) [MSC v.1500 32 bit
win32
Type "help", "copyright", "credits" or "license" for more informatio
>>> 4 is not None
True
>>> True is not None
True
>>> False is not None
True
>>> None is not None
False
>>>

Looks to me like
x is not None

is equivalent to
not (x is None)

(I get same results for 3.1)

DaveA

Ethan Furman

unread,
Aug 5, 2010, 1:09:04 PM8/5/10
to Python List
Roald de Vries wrote:
> On Aug 5, 2010, at 5:42 PM, wheres pythonmonks wrote:
>> How does "x is not None" make any sense? "not x is None" does make
>> sense.
>>
>> I can only surmise that in this context (preceding is) "not" is not a
>> unary right-associative operator, therefore:
>>
>> x is not None === IS_NOTEQ(X, None)
>>
>> Beside "not in" which seems to work similarly, is there other
>> syntactical sugar like this that I should be aware of?
>
> 'not None' first casts None to a bool, and then applies 'not', so 'x is
> not None' means 'x is True'.

This is not correct. 'is not' is a single operator, and in this case is
checking that the object 'x' is not the same as the object 'None'. No
boolean conversions are done -- False and True have nothing to do with
this example.

Python 2.5.4 (r254:67916, Dec 23 2008, 15:10:54) [MSC v.1310 32 bit
(Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
--> x = 5
--> x is not None
True
--> x = True
--> x is not None
True
--> x = ('this','is','a','tuple')
--> x is not None
True
--> x = None
--> x is not None
False

~Ethan~

Benjamin Kaplan

unread,
Aug 5, 2010, 6:44:07 PM8/5/10
to Python List
On Thu, Aug 5, 2010 at 9:07 AM, wheres pythonmonks
<wherespy...@gmail.com> wrote:
> Well, I am not convinced of the equivalence of not None and true:
>
>>>> not None
> True
>>>> 3 is True;
> False
>>>> 3 is not None
> True
>>>>
>
> P.S. Sorry for the top-post -- is there a way to not do top posts from
> gmail?  I haven't used usenet since tin.
>

Scroll down in the email and press enter a few times.

Rhodri James

unread,
Aug 5, 2010, 7:15:38 PM8/5/10
to
On Thu, 05 Aug 2010 17:07:53 +0100, wheres pythonmonks
<wherespy...@gmail.com> wrote:

> Well, I am not convinced of the equivalence of not None and true:
>
>>>> not None
> True
>>>> 3 is True;
> False
>>>> 3 is not None
> True
>>>>

You're not testing for equivalence there, you're testing for identity.
"is" and "is not" test whether the two objects concerned are (or are not)
the same object. Two objects can have the same value, but be different
objects. The interpreter can fool you by caching and reusing objects
which have the same value when it happens to know about it, in particular
for small integers, but this is just a happy accident of the
implementation and in no way guaranteed by the language. For example:

>>> "spam, eggs, chips and spam" is "spam, eggs, chips and spam"
True
>>> a = "spam, eggs, chips and spam"
>>> b = "spam, eggs, chips and spam"
>>> a is b
False
>>> a == b
True

Also, remember that "is not" is a single operator, *not* the concatenation
of "is" and "not". Your last test is probably not checking what you think
it is :-)

>>> 3 is (not None)
False

--
Rhodri James *-* Wildebeest Herder to the Masses

Steven D'Aprano

unread,
Aug 5, 2010, 9:26:42 PM8/5/10
to
On Thu, 05 Aug 2010 12:07:53 -0400, wheres pythonmonks wrote:

> P.S. Sorry for the top-post -- is there a way to not do top posts from
> gmail? I haven't used usenet since tin.

Er, surely you can just move the cursor before you start typing???

--
Steven

Bruno Desthuilliers

unread,
Aug 6, 2010, 3:25:37 AM8/6/10
to
Roald de Vries a écrit :

>
> 'not None' first casts None to a bool, and then applies 'not', so 'x is
> not None' means 'x is True'.

Obviously plain wrong :

Python 2.6.2 (release26-maint, Apr 19 2009, 01:56:41)
[GCC 4.3.3] on linux2


Type "help", "copyright", "credits" or "license" for more information.

>>> 42 is not None
True
>>> 42 is True
False
>>>

Please check your facts before posting !-)

Richard D. Moores

unread,
Aug 6, 2010, 3:26:49 AM8/6/10
to Rhodri James, pytho...@python.org
On Thu, Aug 5, 2010 at 16:15, Rhodri James <rho...@wildebst.demon.co.uk> wrote:
> On Thu, 05 Aug 2010 17:07:53 +0100, wheres pythonmonks
> <wherespy...@gmail.com> wrote:

> You're not testing for equivalence there, you're testing for identity.  "is"
> and "is not" test whether the two objects concerned are (or are not) the
> same object.  Two objects can have the same value, but be different objects.
>  The interpreter can fool you by caching and reusing objects which have the
> same value when it happens to know about it, in particular for small
> integers, but this is just a happy accident of the implementation and in no
> way guaranteed by the language.  For example:
>
>>>> "spam, eggs, chips and spam" is "spam, eggs, chips and spam"
>
> True
>>>>
>>>> a = "spam, eggs, chips and spam"
>>>> b = "spam, eggs, chips and spam"
>>>> a is b
>
> False
>>>>
>>>> a == b
>
> True
>

I'm wondering if there isn't considerable predictability to that
"happy accident". Note how 1 'word' is treated versus 2:

>>> x = 'alksjdhflkajshdflkajhdflkjahsdflkjshadflkjhsadlfkjhaslkdjfhslkadhflkjshdflkjshdflkjshdfk'
>>> y = 'alksjdhflkajshdflkajhdflkjahsdflkjshadflkjhsadlfkjhaslkdjfhslkadhflkjshdflkjshdflkjshdfk'
>>> x is y
True
>>> x = 'alksjdhflkajshdflkajhdflkjahsdflkj hadflkjhsadlfkjhaslkdjfhslkadhflkjshdflkjshdflkjshdfk'
>>> y = 'alksjdhflkajshdflkajhdflkjahsdflkj hadflkjhsadlfkjhaslkdjfhslkadhflkjshdflkjshdflkjshdfk'
>>> x is y
False
>>>

(Python 3.1 on Vista.)

Dick Moores

Bruno Desthuilliers

unread,
Aug 6, 2010, 4:32:00 AM8/6/10
to
Richard D. Moores a écrit :

> On Thu, Aug 5, 2010 at 16:15, Rhodri James <rho...@wildebst.demon.co.uk> wrote:
>> On Thu, 05 Aug 2010 17:07:53 +0100, wheres pythonmonks
>> <wherespy...@gmail.com> wrote:
>
>> You're not testing for equivalence there, you're testing for identity. "is"
>> and "is not" test whether the two objects concerned are (or are not) the
>> same object. Two objects can have the same value, but be different objects.
>> The interpreter can fool you by caching and reusing objects which have the
>> same value when it happens to know about it, in particular for small
>> integers, but this is just a happy accident of the implementation and in no
>> way guaranteed by the language. For example:
>>
>>>>> "spam, eggs, chips and spam" is "spam, eggs, chips and spam"
>> True
>>>>> a = "spam, eggs, chips and spam"
>>>>> b = "spam, eggs, chips and spam"
>>>>> a is b
>> False
>>>>> a == b
>> True
>>
>
> I'm wondering if there isn't considerable predictability to that
> "happy accident".

There is, indeed, but that's really implementation details.

> Note how 1 'word' is treated versus 2:
>
>>>> x = 'alksjdhflkajshdflkajhdflkjahsdflkjshadflkjhsadlfkjhaslkdjfhslkadhflkjshdflkjshdflkjshdfk'
>>>> y = 'alksjdhflkajshdflkajhdflkjahsdflkjshadflkjhsadlfkjhaslkdjfhslkadhflkjshdflkjshdflkjshdfk'
>>>> x is y
> True
>>>> x = 'alksjdhflkajshdflkajhdflkjahsdflkj hadflkjhsadlfkjhaslkdjfhslkadhflkjshdflkjshdflkjshdfk'
>>>> y = 'alksjdhflkajshdflkajhdflkjahsdflkj hadflkjhsadlfkjhaslkdjfhslkadhflkjshdflkjshdflkjshdfk'
>>>> x is y
> False


CPython caches strings that happen to be valid Python identifiers. But
once again, this is an implementation-specific optimization.

Richard D. Moores

unread,
Aug 6, 2010, 5:27:11 AM8/6/10
to pytho...@python.org

So there would be a different implementation for each operating
system? One for Windows, one for linux? Or one for Vista and one for
XP? I'm just trying to clarify what is meant by "implementation".

Thanks,

Dick Moores

Jean-Michel Pichavant

unread,
Aug 6, 2010, 5:42:39 AM8/6/10
to Steven D'Aprano, pytho...@python.org
CTRL+END will bring the cursor at the end of the file (for most the the
mail clients).


JM

Roald de Vries

unread,
Aug 6, 2010, 6:01:23 AM8/6/10
to Python List
On Aug 6, 2010, at 9:25 AM, Bruno Desthuilliers wrote:
> Roald de Vries a écrit :
>> 'not None' first casts None to a bool, and then applies 'not', so
>> 'x is not None' means 'x is True'.
>
> Obviously plain wrong :
>
> Python 2.6.2 (release26-maint, Apr 19 2009, 01:56:41)
> [GCC 4.3.3] on linux2
> Type "help", "copyright", "credits" or "license" for more information.
> >>> 42 is not None
> True
> >>> 42 is True
> False
> >>>

I know. I'm sorry. I'm embarrassed. I will check my facts better
before posting in the future. And I'm sorry.

Cheers, Roald

Vito 'ZeD' De Tullio

unread,
Aug 6, 2010, 7:12:44 AM8/6/10
to pytho...@python.org
Richard D. Moores wrote:

> So there would be a different implementation
for each operating
> system? One for Windows, one for linux? Or one for
Vista and one for
> XP? I'm just trying to clarify what is meant by
"implementation".

there are dozillions of "implementation" of python: one
for each release of CPython (2.0, 2.1.2, 2.6.1, 3.x.y...), multiplied for
each OS multiplied for IronPython, Jython, Pypy... etc...

(obviously the
"implementation details" between, say, CPython 2.6.1 and 2.6.2 are really
minor vs Pypy X.Y.Z and IronPython A.B.C)

--
By ZeD


DG

unread,
Aug 6, 2010, 8:28:40 AM8/6/10
to
On Aug 6, 2:32 am, Bruno Desthuilliers <bruno.

I've always thought of it as you don't compare strings with "is", you
*should* use == The reasoning is that you don't know if that string
instance is the only one in memory. I've heard as an implementation
detail, since strings are immutable, that Python will only create one
actual instance and just assign new references to it (your first x is
y example), but to compare equality it just makes sense to use "==",
not to ask if it is the same object in memory. Plus, I believe the
"==" operator will check if the variables point to the same object.

Using is/is not with None works well, because I believe there will
always only be 1 None object.

Stefan Schwarzer

unread,
Aug 6, 2010, 9:37:04 AM8/6/10
to
Hi DG,

On 2010-08-06 14:28, DG wrote:
> I've always thought of it as you don't compare strings with "is", you
> *should* use == The reasoning is that you don't know if that string
> instance is the only one in memory. I've heard as an implementation
> detail, since strings are immutable, that Python will only create one
> actual instance and just assign new references to it (your first x is
> y example), but to compare equality it just makes sense to use "==",
> not to ask if it is the same object in memory.

Yes, you'd usually use == to compare strings. The use in the
post presumably was to show the behavior when you use `is`;
I guess it wasn't meant as an example for production code. :)

I can imagine a case where you might want to compare a
string with `is`:

FORWARD = "forward"
BACKWARD = "backward"

...

def func(direction=FORWARD):
if direction is FORWARD:
...
elif direction is BACKWARD:
...
else:
...

in case you expect people to specifically use the constants
you provided in the module. Here, the fact that FORWARD
actually is the string "forward" might be considered an
implementation detail. Using a string instead of an
`object()` has the advantage that it makes usage in error
messages easier.

Actually, I've never seen such a use, as far as I remember.
What do other people here think? Is the code above, which
compares strings with `is`, bad style, and if yes, why? How
would you write the code instead?

> Plus, I believe the
> "==" operator will check if the variables point to the same object.

No, that's what `is` is for.

> Using is/is not with None works well, because I believe there will
> always only be 1 None object.

Yes, and it avoids subtle bugs if someone overwrites `__eq__`
in some class:

>>> class AlwaysEqual(object):
... def __eq__(self, other):
... return True
...
>>> always_equal = AlwaysEqual()
>>> always_equal == None
True
>>> None == always_equal
True
>>> always_equal is None
False

Stefan

Peter Pearson

unread,
Aug 6, 2010, 1:20:30 PM8/6/10
to
On Fri, 06 Aug 2010 15:37:04 +0200, Stefan Schwarzer wrote:
[snip]

> I can imagine a case where you might want to compare a
> string with `is`:
>
> FORWARD = "forward"
> BACKWARD = "backward"
>
> ...
>
> def func(direction=FORWARD):
> if direction is FORWARD:
> ...
> elif direction is BACKWARD:
> ...
> else:
> ...
>
> in case you expect people to specifically use the constants
> you provided in the module. Here, the fact that FORWARD
> actually is the string "forward" might be considered an
> implementation detail. Using a string instead of an
> `object()` has the advantage that it makes usage in error
> messages easier.
>
> Actually, I've never seen such a use, as far as I remember.
> What do other people here think? Is the code above, which
> compares strings with `is`, bad style, and if yes, why? How
> would you write the code instead?

Hey, that's a cute example, but . . . what a trap! Is it
possible to document the use-the-object-not-the-string requirement
loudly enough that people won't get caught?

--
To email me, substitute nowhere->spamcop, invalid->net.

Terry Reedy

unread,
Aug 6, 2010, 2:20:45 PM8/6/10
to pytho...@python.org
On 8/6/2010 5:27 AM, Richard D. Moores wrote:

> So there would be a different implementation for each operating
> system? One for Windows, one for linux? Or one for Vista and one for
> XP? I'm just trying to clarify what is meant by "implementation".

Different version of CPython (that string caching bit has changed in the
past) and CPython versus Jython, PyPy, IronPython, Cython, etc.

--
Terry Jan Reedy

Stefan Schwarzer

unread,
Aug 6, 2010, 2:36:26 PM8/6/10
to
Hello Peter,

On 2010-08-06 19:20, Peter Pearson wrote:
> On Fri, 06 Aug 2010 15:37:04 +0200, Stefan Schwarzer wrote:
> [snip]
>> I can imagine a case where you might want to compare a
>> string with `is`:
>>
>> FORWARD = "forward"
>> BACKWARD = "backward"
>>
>> ...
>>
>> def func(direction=FORWARD):
>> if direction is FORWARD:
>> ...
>> elif direction is BACKWARD:
>> ...
>> else:
>> ...

>> [...]

> Hey, that's a cute example,

Thanks!

> but . . . what a trap! Is it
> possible to document the use-the-object-not-the-string requirement
> loudly enough that people won't get caught?

That's a good question, actually that's the nagging problem
I also have with the approach.

In production code I might write

# Use _these_ objects to indicate directions, not string
# constants with the same value.


FORWARD = "forward"
BACKWARD = "backward"

However, that won't help if people import the module and see
the strings under "global data" and so assume they're "just
strings". Moreover, if you have to write such a comment for
every use of the idiom the conciseness of the approach
vanishes.

Another view at the matter would be to let clients of the
module find out their mistake by unit tests. But of course
that's somewhat doubtful as the intention should be to write
robust instead of bug-inviting code.

I wonder if there's a way to have both the "cuteness" of the
string constants _and_ more robustness.

Stefan

Ethan Furman

unread,
Aug 6, 2010, 3:34:24 PM8/6/10
to pytho...@python.org

Instead of using 'is' use '=='. Maybe not as cute, but definitely more
robust!

~Ethan~

Steven D'Aprano

unread,
Aug 6, 2010, 6:13:50 PM8/6/10
to
On Fri, 06 Aug 2010 17:20:30 +0000, Peter Pearson wrote:

> On Fri, 06 Aug 2010 15:37:04 +0200, Stefan Schwarzer wrote: [snip]
>> I can imagine a case where you might want to compare a string with
>> `is`:
>>
>> FORWARD = "forward"
>> BACKWARD = "backward"

[...]


>> Actually, I've never seen such a use, as far as I remember. What do
>> other people here think? Is the code above, which compares strings with
>> `is`, bad style, and if yes, why? How would you write the code instead?
>
> Hey, that's a cute example, but . . . what a trap! Is it possible to
> document the use-the-object-not-the-string requirement loudly enough
> that people won't get caught?

Nope. People don't read documentation :)

That's why I prefer to test for human-readable constants using equality,
so if the caller prefers to call func(x, "forward") instead of func(x,
FORWARD) it will still work.

Or I use

FOWARD = object()
BACKWARDS = object()

and force them to use my constants.

--
Steven

Steven D'Aprano

unread,
Aug 6, 2010, 6:23:05 PM8/6/10
to
On Fri, 06 Aug 2010 05:28:40 -0700, DG wrote:

> I've always thought of it as you don't compare strings with "is", you
> *should* use == The reasoning is that you don't know if that string
> instance is the only one in memory.

This is excellent advice. I won't say that there is "never" a use-case
for testing strings for identity, but I can't think of one that isn't
contrived and artificial.


> I've heard as an implementation
> detail, since strings are immutable, that Python will only create one
> actual instance and just assign new references to it (your first x is y
> example), but to compare equality it just makes sense to use "==", not
> to ask if it is the same object in memory. Plus, I believe the "=="
> operator will check if the variables point to the same object.

Yes, that is an optimization that CPython performs. Other implementations
may do different, but the optimization is so obvious and so cheap that I
would be shocked if any of the major implementations fail to do so.


> Using is/is not with None works well, because I believe there will
> always only be 1 None object.

Yes, that is correct, but there's also a semantic difference. Generally,
when testing for None, you actually want None and not some look-alike
that merely tests equal to None. You want to "accept no substitutes", and
so an identity test is necessary.

--
Steven

Steven D'Aprano

unread,
Aug 6, 2010, 6:28:52 PM8/6/10
to
On Fri, 06 Aug 2010 15:37:04 +0200, Stefan Schwarzer wrote:

>> Plus, I believe the
>> "==" operator will check if the variables point to the same object.
>
> No, that's what `is` is for.

Actually, yes, equality is implemented with a short-cut that checks for
identity first. That makes something like:

s = "abc"*1000*1000*10
s == s

nice and quick, as Python can immediately recognise that a string is
always equal to itself without having to walk the entire string comparing
each character with itself.

--
Steven

Steven D'Aprano

unread,
Aug 6, 2010, 6:32:11 PM8/6/10
to

Bottom-posting is just as annoying as top-posting, except for very short
posts like this. Posting in-line, where you trim the excess quoting to
leave enough to give context, is most recommended.


--
Steven

Gregory Ewing

unread,
Aug 6, 2010, 9:36:30 PM8/6/10
to
Ethan Furman wrote:

> Instead of using 'is' use '=='. Maybe not as cute, but definitely more
> robust!

It's also just as efficient if you use strings that
resemble identifiers, because they will be interned,
so the comparison will end up just doing an indentity
test anyway.

--
Greg

Gregory Ewing

unread,
Aug 6, 2010, 9:41:03 PM8/6/10
to
Steven D'Aprano wrote:
> Generally,
> when testing for None, you actually want None and not some look-alike
> that merely tests equal to None.

That's true, although I can't think of a use case for an object
that compares equal to None but isn't -- except for obfuscated
code competition entries and making obscure points in usenet
discussions. :-)

--
Greg

Ben Finney

unread,
Aug 7, 2010, 12:28:19 AM8/7/10
to

I like to think that the cursor is placed at the top by default so that
<URL:http://en.wikipedia.org/wiki/Posting_style#Interleaved_style> is
easy: just travel down through the quoted material, removing it if not
relevant and inserting one's responses where needed.

--
\ “Two hands working can do more than a thousand clasped in |
`\ prayer.” —Anonymous |
_o__) |
Ben Finney

Stefan Schwarzer

unread,
Aug 7, 2010, 3:04:06 AM8/7/10
to
Hi Steven,

On 2010-08-07 00:28, Steven D'Aprano wrote:
> On Fri, 06 Aug 2010 15:37:04 +0200, Stefan Schwarzer wrote:
>>> Plus, I believe the
>>> "==" operator will check if the variables point to the same object.
>>
>> No, that's what `is` is for.
>
> Actually, yes, equality is implemented with a short-cut that checks for
> identity first. That makes something like:

> [...]

Oops, I didn't realize that the OP had mentioned the
identity check as an optimization in case the objects are
the same. I thought he was confusing the operator with `is`.

> s = "abc"*1000*1000*10
> s == s
>
> nice and quick, as Python can immediately recognise that a string is
> always equal to itself without having to walk the entire string comparing
> each character with itself.

Yes, that definitely makes sense. I guess I would have
implemented it this way as well. :)

Stefan

Gabriel Genellina

unread,
Aug 7, 2010, 3:44:19 AM8/7/10
to pytho...@python.org
En Sat, 07 Aug 2010 04:04:06 -0300, Stefan Schwarzer
<sschw...@sschwarzer.net> escribió:

For strings and other internal types this optimization certainly makes
sense. For user-defined types it gets in the way and prevents defining an
object such x==x is False (like NANs).

--
Gabriel Genellina

Steven D'Aprano

unread,
Aug 7, 2010, 8:05:02 AM8/7/10
to
On Sat, 07 Aug 2010 14:28:19 +1000, Ben Finney wrote:

> Steven D'Aprano <st...@REMOVE-THIS-cybersource.com.au> writes:
>
>> On Thu, 05 Aug 2010 12:07:53 -0400, wheres pythonmonks wrote:
>>
>> > P.S. Sorry for the top-post -- is there a way to not do top posts
>> > from gmail? I haven't used usenet since tin.
>>
>> Er, surely you can just move the cursor before you start typing???
>
> I like to think that the cursor is placed at the top by default so that
> <URL:http://en.wikipedia.org/wiki/Posting_style#Interleaved_style> is
> easy: just travel down through the quoted material, removing it if not
> relevant and inserting one's responses where needed.

Yes, but apparently millions of Internet users have keyboards where
neither the cursor keys nor backspace/delete works. Being unable to
interleave their reply with the quoted text, they end up quoting the
entire week-long thread at the bottom of every email they send.

I blame Manservant Neville.


--
Steven

Thomas Jollans

unread,
Aug 7, 2010, 8:28:48 AM8/7/10
to pytho...@python.org
On 08/07/2010 09:44 AM, Gabriel Genellina wrote:
> En Sat, 07 Aug 2010 04:04:06 -0300, Stefan Schwarzer
> <sschw...@sschwarzer.net> escribió:
> For strings and other internal types this optimization certainly makes
> sense. For user-defined types it gets in the way and prevents defining
> an object such x==x is False (like NANs).
>

That's probably why this optimisation doesn't exist for user-defined types:

Python 3.1.2 (release31-maint, Jul 8 2010, 09:18:08)
[GCC 4.4.4] on linux2


Type "help", "copyright", "credits" or "license" for more information.
>>>

>>> class A:
... def __eq__(self, x):
... if self is x: return False
... else: return True
...
>>>
>>> A() == A()
True
>>> a = A()
>>> a == a
False
>>>

Ben Finney

unread,
Aug 7, 2010, 7:16:26 PM8/7/10
to
Peter Pearson <ppea...@nowhere.invalid> writes:

> Hey, that's a cute example, but . . . what a trap! Is it possible to
> document the use-the-object-not-the-string requirement loudly enough
> that people won't get caught?

Don't use strings for such values. The data isn't going to be used, so
there's no sense using a semantically rich data type like a string.

Instead, use an ‘object’ instance; then, the only way to get a binding
that will compare equal is to use the very object itself.

FORWARD = object()
BACKWARD = object()

--
\ “Never do anything against conscience even if the state demands |
`\ it.” —Albert Einstein |
_o__) |
Ben Finney

Message has been deleted

Stefan Schwarzer

unread,
Aug 8, 2010, 3:46:40 AM8/8/10
to
Hi Ben,

On 2010-08-08 01:16, Ben Finney wrote:
> Don't use strings for such values. The data isn't going to be used, so
> there's no sense using a semantically rich data type like a string.
>
> Instead, use an ‘object’ instance; then, the only way to get a binding
> that will compare equal is to use the very object itself.
>
> FORWARD = object()
> BACKWARD = object()

Yes, that's the obvious approach. :-) I had used strings in
the example with the reasoning that they could be readily
used in messages (from my post: "Using a string instead of


an `object()` has the advantage that it makes usage in error

messages easier.").

For the record, another approach I've seen is something like

FORWARD, BACKWARD, UNKNOWN = range(3)

This has the same problem as when using strings for the
constants but looking at the module contents it's a bit
more obvious that these are just "magic numbers", so
presumably the constant names should be used instead.

Stefan

Albert van der Horst

unread,
Aug 8, 2010, 11:12:16 AM8/8/10
to
In article <8c2uiu...@mid.individual.net>,

king = "This is just a string for denoting a chess object, \
if a field contains (a reference to) king, it means the piece \
is standing on that field"

Even a fresh convert from the Java language would not insert the
string instead of the name of the object.

(In practive you want black kings and white kings to be different
objects, probably.)

>
>--
>To email me, substitute nowhere->spamcop, invalid->net.


--
--
Albert van der Horst, UTRECHT,THE NETHERLANDS
Economic growth -- being exponential -- ultimately falters.
albert@spe&ar&c.xs4all.nl &=n http://home.hccnet.nl/a.w.m.van.der.horst

Bruno Desthuilliers

unread,
Aug 9, 2010, 5:04:40 AM8/9/10
to
Gregory Ewing a écrit :

> Ethan Furman wrote:
>
>> Instead of using 'is' use '=='. Maybe not as cute, but definitely
>> more robust!
>
> It's also just as efficient if you use strings that
> resemble identifiers, because they will be interned,

Remember : this IS an implementation detail.

saeed.gnu

unread,
Aug 9, 2010, 7:41:23 AM8/9/10
to
"x is y" means "id(y) == id(y)"
"x is not y" means "id(x) != id(x)"
"x is not None" means "id(x) != id(None)"

"x is not None" is a really silly statement!! because id(None) and id
of any constant object is not predictable! I don't know whay people
use "is" instead of "==". you should write "if x!=None" instead of "x
is not None"

saeed.gnu

unread,
Aug 9, 2010, 8:11:11 AM8/9/10
to

Although small objects are unique in the memory (with a unique id) and
using "is" works ok, but that's not logical to compare id's when we
actually want to compare values!

Dave Angel

unread,
Aug 9, 2010, 10:21:38 AM8/9/10
to saeed.gnu, pytho...@python.org
saeed.gnu wrote:
> On Aug 9, 3:41 pm, "saeed.gnu" <saeed....@gmail.com> wrote:
>
>> "x is y" means "id(y) =id(y)"
>> "x is not y" means "id(x) !=d(x)"
>> "x is not None" means "id(x) !=d(None)"

>>
>> "x is not None" is a really silly statement!! because id(None) and id
>> of any constant object is not predictable! I don't know whay people
>> use "is" instead of "=. you should write "if x!=None" instead of "x

>> is not None"
>>
>
> Although small objects are unique in the memory (with a unique id) and
> using "is" works ok, but that's not logical to compare id's when we
> actually want to compare values!
>
>
None is a single object; there is only one such object by language
definition. So 'is' is the perfect operator if you want to check
whether a particular object is that one or not. All other objects, of
any possible type, will have a different ID than None.

And talking about comparing values is nonsense anyway, since None has no
value. It's only purpose is to indicate that some operation had no
value, or no return statement, or ...

Using '==' will not necessarily give the same result, and I can't think
of ANY case where I'd prefer the former. If you disagree, give a
concrete example.

DaveA


DaveA

Nobody

unread,
Aug 9, 2010, 10:56:09 AM8/9/10
to
On Mon, 09 Aug 2010 04:41:23 -0700, saeed.gnu wrote:

> "x is not None" is a really silly statement!! because id(None) and id
> of any constant object is not predictable! I don't know whay people
> use "is" instead of "==". you should write "if x!=None" instead of "x
> is not None"

No, you should use the identity check. If you use ==, the operand
may have an __eq__ or __cmp__ method which considers the object equal to
None.

Terry Reedy

unread,
Aug 9, 2010, 12:28:17 PM8/9/10
to pytho...@python.org
On 8/9/2010 7:41 AM, saeed.gnu wrote:
> "x is y" means "id(y) == id(y)"
> "x is not y" means "id(x) != id(x)"
> "x is not None" means "id(x) != id(None)"
>
> "x is not None" is a really silly statement!!

Wrong. It is exactly right when that is what one means and is the
STANDARD IDIOM.

> because id(None) and id
> of any constant object is not predictable!

This is silly. The id of None and of any other object are predictably
different.

> I don't know whay people use "is" instead of "==".

Because it is the right thing to do!

> you should write "if x!=None" instead of "x is not None"

Wrong. It is trivial to make a class whose objects compare == to None.

--
Terry Jan Reedy

Gabriel Genellina

unread,
Aug 9, 2010, 4:14:26 PM8/9/10
to pytho...@python.org
En Mon, 09 Aug 2010 08:41:23 -0300, saeed.gnu <saee...@gmail.com>
escribió:

> "x is y" means "id(y) == id(y)"
> "x is not y" means "id(x) != id(x)"

No; consider this:


py> id([])==id([])
True
py> [] is []
False

Comparing id's is the same as using the is operator only if you can
guarantee that both operands are alive at the same time.


--
Gabriel Genellina

Michael Torrie

unread,
Aug 9, 2010, 5:13:04 PM8/9/10
to pytho...@python.org

Sounds like you're confusing Python's namespace with variables. When I say:

a = None

I'm binding the None object to the a name. Thus a *is*
None. While in theory "None" does have a value, doing "a is None" is
much more explicit and clearer than "a == None" although perhaps the
result is the same. In any event "a is None" is actually logical
because that's what I'm normally interested in. Whether or not a is
None. I don't really care about the value of None.


Ben Finney

unread,
Aug 9, 2010, 9:18:35 PM8/9/10
to
"saeed.gnu" <saee...@gmail.com> writes:

> "x is y" means "id(y) == id(y)"
> "x is not y" means "id(x) != id(x)"
> "x is not None" means "id(x) != id(None)"

No, the meanings are different. The behaviour might, or might not, be
the same. The operators are different *because* the meanings are
different.

> "x is not None" is a really silly statement!! because id(None) and id
> of any constant object is not predictable!

The value returned from ‘id’ is not predictable; but it doesn't need to
be predictable. It merely needs to obey the invariant that the identity
of any given object won't change during the object's lifetime.

--
\ “You've got the brain of a four-year-old boy, and I'll bet he |
`\ was glad to get rid of it.” —Groucho Marx |
_o__) |
Ben Finney

Jean-Michel Pichavant

unread,
Aug 10, 2010, 5:19:33 AM8/10/10
to Ben Finney, pytho...@python.org
Ben Finney wrote:
> Peter Pearson <ppea...@nowhere.invalid> writes:
>
>
>> Hey, that's a cute example, but . . . what a trap! Is it possible to
>> document the use-the-object-not-the-string requirement loudly enough
>> that people won't get caught?
>>
>
> Don't use strings for such values. The data isn't going to be used, so
> there's no sense using a semantically rich data type like a string.
>
> Instead, use an ‘object’ instance; then, the only way to get a binding
> that will compare equal is to use the very object itself.
>
> FORWARD = object()
> BACKWARD = object()
>
>
Strings may have their use, most of the time providing a string
representation of the object, here is an example:

FORWARD = object()

print 'moving %s' % FORWARD
> moving <object object at 0xb7dab5a8>

Another approach using strings:

class Direction:
FORWARD = 'forward'

print "moving %s' % Direction.FORWARD
> moving forward

Note that
Direction.FORWARD is Direction.FORWARD
is safe and will return True.

JM


Matt Schinckel

unread,
Aug 12, 2010, 10:52:07 PM8/12/10
to
On Aug 6, 8:15 am, "Rhodri James" <rho...@wildebst.demon.co.uk> wrote:
> On Thu, 05 Aug 2010 17:07:53 +0100, wheres pythonmonks  
>
> <wherespythonmo...@gmail.com> wrote:
> > Well, I am not convinced of the equivalence of not None and true:
[snip]
> >>> "spam, eggs, chips and spam" is "spam, eggs, chips and spam"
> True
> >>> a = "spam, eggs, chips and spam"
> >>> b = "spam, eggs, chips and spam"
> >>> a is b
> False

but:

>>> a = "hello"
>>> b = "hello"
>>> a is b
True

Ooh, that looks dangerous. Are they the same object?

>>> a += "o"
>>> a
'helloo'
>>> b
'hello'

Phew.

(Python does not make two copies of small strings until it needs to).

Matt.

Terry Reedy

unread,
Aug 13, 2010, 1:12:10 AM8/13/10
to pytho...@python.org
On 8/12/2010 10:52 PM, Matt Schinckel wrote:

>>>> a = "hello"
>>>> b = "hello"
>>>> a is b
> True
>
> Ooh, that looks dangerous.

Only for mutable objects

> Are they the same object?

Yes.

>>>> a += "o"

This is equivalent to a = a+"o". The expression creates a new object.
The assignment binds the object to name 'a'.

> (Python does not make two copies of small strings until it needs to).

Python never copies *any* object until you ask it to. It never made a
copy of the original 'a' here either. It combined the values of two
string objects to make a new string object with a new value.

--
Terry Jan Reedy

Steven D'Aprano

unread,
Aug 13, 2010, 2:03:54 AM8/13/10
to
On Thu, 12 Aug 2010 19:52:07 -0700, Matt Schinckel wrote:

>>>> a = "hello"
>>>> b = "hello"
>>>> a is b
> True
>
> Ooh, that looks dangerous. Are they the same object?


You don't need another test to know that they are the same object. The
`is` operator does exactly that: a is b *only* if a and b are the same
object.


>>>> a += "o"
>>>> a
> 'helloo'
>>>> b
> 'hello'
>
> Phew.

This tests for mutability, not sameness. If strings were mutable, then
modifying a in place would likewise cause b to be modified (because they
are the same object). Here's an example:

>>> a = b = [1, 2, 3]
>>> a is b
True
>>> a += [4]
>>> b
[1, 2, 3, 4]

But of course, if strings were mutable like lists, they wouldn't be
cached! The consequences would be horrific if they were, unless Python's
execution model were radically different. Copy-on-write perhaps?


> (Python does not make two copies of small strings until it needs to).

Python doesn't copy anything unless you ask it to.

--
Steven

0 new messages