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
'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
"is not" is an operator, not the combination of 2.
JM
> 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
>>> 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
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
Absolutely incorrect. Read the final paragraph of
http://docs.python.org/reference/expressions.html#notin
Cheers,
Chris
--
http://blog.rebertia.com
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
Oops, sorry :$.
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
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~
Scroll down in the email and press enter a few times.
> 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
> 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
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 !-)
> 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
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.
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
JM
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
> 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
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.
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
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.
> 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
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
Instead of using 'is' use '=='. Maybe not as cute, but definitely more
robust!
~Ethan~
> 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
> 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
>> 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
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
> 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
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
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
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
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 <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
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
>>>
> 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
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
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
Remember : this IS an implementation detail.
"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!
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
> "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.
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
> "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
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.
> "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
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
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.
>>>> 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
>>>> 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