Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #16262 > unrolled thread

Pragmatics of the standard is() function

Started bycandide <candide@free.invalid>
First post2011-11-26 22:20 +0100
Last post2011-11-28 13:57 +0100
Articles 14 — 9 participants

Back to article view | Back to comp.lang.python


Contents

  Pragmatics of the standard is() function candide <candide@free.invalid> - 2011-11-26 22:20 +0100
    Re: Pragmatics of the standard is() function Roy Smith <roy@panix.com> - 2011-11-26 16:32 -0500
    Re: Pragmatics of the standard is() function Chris Angelico <rosuav@gmail.com> - 2011-11-27 09:22 +1100
    Re: Pragmatics of the standard is() function Alexander Kapps <alex.kapps@web.de> - 2011-11-26 23:38 +0100
    Re: Pragmatics of the standard is() function Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2011-11-26 23:01 +0000
      Re: Pragmatics of the is operator candide <candide@free.invalid> - 2011-11-27 02:42 +0100
        Re: Pragmatics of the is operator Chris Angelico <rosuav@gmail.com> - 2011-11-27 12:50 +1100
        Re: Pragmatics of the is operator Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2011-11-27 03:13 +0000
      Re: Pragmatics of the standard is() function Den <patentsvnc@gmail.com> - 2011-11-28 11:22 -0800
        Re: Pragmatics of the standard is() function Ethan Furman <ethan@stoneleaf.us> - 2011-11-28 12:05 -0800
        Re: Pragmatics of the standard is() function alex23 <wuwei23@gmail.com> - 2011-11-28 19:58 -0800
        Re: Pragmatics of the standard is() function Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2011-11-29 08:41 +0000
          Re: Pragmatics of the standard is() function Den <patentsvnc@gmail.com> - 2011-11-29 09:11 -0800
    Re: Pragmatics of the standard is() function Jean-Michel Pichavant <jeanmichel@sequans.com> - 2011-11-28 13:57 +0100

#16262 — Pragmatics of the standard is() function

Fromcandide <candide@free.invalid>
Date2011-11-26 22:20 +0100
SubjectPragmatics of the standard is() function
Message-ID<4ed15825$0$21841$426a34cc@news.free.fr>
In which cases should we use the is() function ? The is() function 
compares identity of objects rather than values so I was wondering in 
which circumstances comparing identities of objects is really vital.

Examining well reputated Python source code, I realize that is() 
function is mainly used in the following set form :

spam is None

But how much "spam is None" is different from "spam == None" ?



is() function makes comparaison of (abstract representation of) adresses 
of objects in memory. Comparing addresses of objects is a low level 
feature performed by low level langages such as C but seldom needed in 
high level languages like Python, isn'it ?

[toc] | [next] | [standalone]


#16263

FromRoy Smith <roy@panix.com>
Date2011-11-26 16:32 -0500
Message-ID<roy-F5D2BF.16321726112011@news.panix.com>
In reply to#16262
In article <4ed15825$0$21841$426a34cc@news.free.fr>,
 candide <candide@free.invalid> wrote:

> In which cases should we use the is() function ? The is() function 
> compares identity of objects rather than values so I was wondering in 
> which circumstances comparing identities of objects is really vital.
> 
> Examining well reputated Python source code, I realize that is() 
> function is mainly used in the following set form :
> 
> spam is None
> 
> But how much "spam is None" is different from "spam == None" ?

It's the difference between *being* None, and being equal to None.  For 
example:

class Spam:
    def __eq__(self, other):
        return not other

spam = Spam()
print spam is None
print spam == None

When I run that, it prints:

False
True

In practice, when you compare something to None, you usually want the 
"is" form.  In cases where either would work (i.e. 99% of the time), 
it's convention (and/or good practice) to use "is" because it more more 
clearly expresses what it is that you're trying to do.

[toc] | [prev] | [next] | [standalone]


#16265

FromChris Angelico <rosuav@gmail.com>
Date2011-11-27 09:22 +1100
Message-ID<mailman.3060.1322346163.27778.python-list@python.org>
In reply to#16262
On Sun, Nov 27, 2011 at 8:20 AM, candide <candide@free.invalid> wrote:
> is() function makes comparaison of (abstract representation of) adresses of
> objects in memory. Comparing addresses of objects is a low level feature
> performed by low level langages such as C but seldom needed in high level
> languages like Python, isn'it ?

You also want 'is' when you're testing for a singleton used as a default value:

DEFAULT = object()

def foo(arg1,arg2,arg3=DEFAULT):
    if arg3 is DEFAULT: print("You gave me two args")


ChrisA

[toc] | [prev] | [next] | [standalone]


#16266

FromAlexander Kapps <alex.kapps@web.de>
Date2011-11-26 23:38 +0100
Message-ID<mailman.3061.1322347054.27778.python-list@python.org>
In reply to#16262
On 26.11.2011 22:20, candide wrote:

You already got answers for the "is" vs. "==" difference. I'd like 
to add the following.

> In which cases should we use the is() function ?

"is" is not a function, It's an operator, just like == or +.

> is() function makes comparaison of (abstract representation of)
> adresses of objects in memory.

That's an implementation detail. CPython (and maybe others) 
implement "is" in terms of memory addresses. Other implementations 
might use an object ID number or whatever else.

[toc] | [prev] | [next] | [standalone]


#16267

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2011-11-26 23:01 +0000
Message-ID<4ed16fb9$0$29988$c3e8da3$5496439d@news.astraweb.com>
In reply to#16262
On Sat, 26 Nov 2011 22:20:36 +0100, candide wrote:

> In which cases should we use the is() function ? The is() function
> compares identity of objects rather than values so I was wondering in
> which circumstances comparing identities of objects is really vital.

`is` is not a function. It is a keyword and an operator.

You should always use `is` when you intend to test for object identity, 
and never use `is` when you do not intend to test for object identity. 
For example:

TASK: check whether a number is equal to 42.

    # WRONG don't do this
    if x is 42: ...
    # RIGHT use equality instead
    if x == 42: ...

Object identity is the wrong solution here, because you cannot control 
whether Python will re-use the same object for every instance of 42, or 
different objects each time.


TASK: check whether an object is a specific sentinel value, and no other 
value, even if it happens to compare equal to the sentinel. The most 
common sentinel is the singleton None.

    # WRONG don't do this
    if x == None: ...
    # RIGHT use is instead
    if x is None: ...


Use of equality is inappropriate, because it tests whether the object 
compares equal to None. Although there are no built-ins that compare 
equal to None, there could be any number of custom objects that do, and 
so your code contains a bug: you intend to branch *only* on None, but 
might branch on some other object by mistake.


> Examining well reputated Python source code, I realize that is()
> function is mainly used in the following set form :
> 
> spam is None
> 
> But how much "spam is None" is different from "spam == None" ?

Even if you can guarantee that your code base does not contain any object 
which compares equal to None except for None itself (and how would you do 
that? a full audit of every line of code in every library you use?), the 
use of `is` should be preferred because it signals your intention much 
better.

If your intention is to accept arbitrary objects which compare equal to 
None, than by all means use == for your comparison. But normally the 
intention is to accept None, and nothing else.


> is() function makes comparaison of (abstract representation of) adresses
> of objects in memory. Comparing addresses of objects is a low level
> feature performed by low level langages such as C but seldom needed in
> high level languages like Python, isn'it ?

That is correct. You probably should rarely use `is`. Apart from testing 
for None, use of `is` should be rare.



-- 
Steven

[toc] | [prev] | [next] | [standalone]


#16270 — Re: Pragmatics of the is operator

Fromcandide <candide@free.invalid>
Date2011-11-27 02:42 +0100
SubjectRe: Pragmatics of the is operator
Message-ID<4ed1959d$0$690$426a74cc@news.free.fr>
In reply to#16267
Thanks to all for your response.


Le 27/11/2011 00:01, Steven D'Aprano a écrit :
> On Sat, 26 Nov 2011 22:20:36 +0100, candide wrote:
>
>> In which cases should we use the is() function ? The is() function
>> compares identity of objects rather than values so I was wondering in
>> which circumstances comparing identities of objects is really vital.
>
> `is` is not a function. It is a keyword and an operator.

oops exponent 10 !! I have in mind the id() function, very close to the 
is operator. An operator named "is" makes search of code snippets  very 
complicated because the verb "is" is always embedded in comments or 
documentation.



>> But how much "spam is None" is different from "spam == None" ?
>
> Even if you can guarantee that your code base does not contain any object
> which compares equal to None except for None itself (and how would you do
> that? a full audit of every line of code in every library you use?), the
> use of `is` should be preferred because it signals your intention much
> better.

OK but tons of good code use "spam == None" ; for instance, many tests 
files in Python official code. A random example (from 
openshot/openshot/windows/MainGTK.py):

# ---------------------------------------------------------------

					parent_name = item.parent
					if parent_name == None:
						match_iter = None

		# Check for NO files
		if mode == None and self.project.project_folder.items.__len__() == 0:
			#switch to the detail view

			
			if drop_track == None:
				# keep old parent, if no track found

		
		if self.new_clip_object == None:
			self.item_detected = False

# ---------------------------------------------------------------



>
> If your intention is to accept arbitrary objects which compare equal to
> None, than by all means use == for your comparison. But normally the
> intention is to accept None, and nothing else.


So, for the same reason, wouldn't it be better to use "if spam is True" 
against to "if spam == True"  (or better "if spam") ?


> That is correct. You probably should rarely use `is`. Apart from testing
> for None, use of `is` should be rare.


OK, thanks

[toc] | [prev] | [next] | [standalone]


#16271 — Re: Pragmatics of the is operator

FromChris Angelico <rosuav@gmail.com>
Date2011-11-27 12:50 +1100
SubjectRe: Pragmatics of the is operator
Message-ID<mailman.3063.1322358656.27778.python-list@python.org>
In reply to#16270
On Sun, Nov 27, 2011 at 12:42 PM, candide <candide@free.invalid> wrote:
> So, for the same reason, wouldn't it be better to use "if spam is True"
> against to "if spam == True"  (or better "if spam") ?
>

They're quite different. "if spam" will check the truthiness of spam -
it's equivalent to "if bool(spam) is True"; "if spam is True" checks
that it's actually a boolean. But I would recommend against the "==
True" form, as it's unclear which form you meant to use. (Others may
disagree.)

ChrisA

[toc] | [prev] | [next] | [standalone]


#16276 — Re: Pragmatics of the is operator

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2011-11-27 03:13 +0000
SubjectRe: Pragmatics of the is operator
Message-ID<4ed1aabc$0$29988$c3e8da3$5496439d@news.astraweb.com>
In reply to#16270
On Sun, 27 Nov 2011 02:42:52 +0100, candide wrote:

>> Even if you can guarantee that your code base does not contain any
>> object which compares equal to None except for None itself (and how
>> would you do that? a full audit of every line of code in every library
>> you use?), the use of `is` should be preferred because it signals your
>> intention much better.
> 
> OK but tons of good code use "spam == None" ; for instance, many tests
> files in Python official code. A random example (from
> openshot/openshot/windows/MainGTK.py):

I don't know what openshot is, but I don't think it is "official" in the 
sense of being in the Python standard library:

>>> import openshot
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: No module named openshot


But even if it were, the standard library is not written by superhuman 
perfect gods, only by ordinary human beings who can make mistakes. 
Comparing against None with == is not idiomatic Python, and is usually a 
mistake. It rarely leads to obvious bugs, so it can survive in code 
without notice for a long time.


>> If your intention is to accept arbitrary objects which compare equal to
>> None, than by all means use == for your comparison. But normally the
>> intention is to accept None, and nothing else.
> 
> 
> So, for the same reason, wouldn't it be better to use "if spam is True"
> against to "if spam == True"  (or better "if spam") ?

No. Normally should just say "if spam" and allow Python to test the 
truthiness of spam.

"if spam == True" is worse, because there are many truthy objects which 
are not equal to True, e.g. 42, "norwegian blue", [1, 2, 3] are all 
truthy objects that (almost always) should be accepted but will wrongly 
be rejected.

"if spam is True" is even worse, because there are many truthy objects 
that are not the True singleton. Old code, especially if it was written 
before the introduction of bools in (I think) 2.1 or 2.2, often uses 1 as 
the standard true-like value. To save typing, many people will still pass 
1 or 0 as an argument when a bool is expected, which will then fail if 
you test for identity.

The exception is if for some reason you actually care whether your flag 
is the True object and absolutely nothing else. This violates Python's 
preference for duck-typing and support for truthiness, but if you have a 
good reason, go right ahead.

Suppose spam is already a bool. Then "if spam" is enough, since spam is a 
bool. "if spam is True" is no more necessary than 

    if spam is True is True
    if spam is True is True is True
    if spam is True is True is True is True 
    if spam is True is True is True is True is True
    if spam is True is True is True is True is True is True
    # I never know when to stop...

The right place to stop is not to start. "if spam is True" is redundant.

And lastly, testing for identity against None is guaranteed by the 
language: any implementation of Python must have None a singleton. But 
True and False are not such a strong promise. A future version of Python, 
or another implementation, might not bother to make True and False 
singletons. (Doubletons?) Unlikely, but why make assumptions that you 
don't need to?



-- 
Steven

[toc] | [prev] | [next] | [standalone]


#16346

FromDen <patentsvnc@gmail.com>
Date2011-11-28 11:22 -0800
Message-ID<c14ce2ad-e2e3-4186-a3a6-3c22aae1ec39@w1g2000vba.googlegroups.com>
In reply to#16267
On Nov 26, 3:01 pm, Steven D'Aprano <steve
+comp.lang.pyt...@pearwood.info> wrote:
> On Sat, 26 Nov 2011 22:20:36 +0100, candide wrote:
>>SNIP<<
>
> That is correct. You probably should rarely use `is`. Apart from testing
> for None, use of `is` should be rare.
>
> --
> Steven

With respect, I disagree with advice that the use of a language
construct should be rare.  All constructs should be used
*appropriately*.

While in general a particular use of a Python construct may be rare,
if the programmer is involved deeply with that rare use, then it is
NOT rare to him/her.  Thus, for a particular programmer, use of 'is'
may be quite frequent because the program they're working on requires
knowledge of object identity.

The same goes for global variables, by the way.  While it's easy to
shoot yourself in the foot with global variables, that doesn't lead to
never-use-them.  It leads to use-them-appropriately-and-carefully.

Sorry, you plucked a string of mine.  One does not throw a tool out of
your tool box because it might be dangerous.  Table saws are
incredibly dangerous, but in the hands of a skilled operator can be
competently and safely used to produce beautiful woodwork.  To say
*never* use a table saw because it's dangerous is silly.

Language constructs are put there intentionally.  Advice that they be
used *rarely* or *never* should *never* be given ((chuckle)).  Just
learn what they are, learn how they work, learn what the consequences
of misuse can be (loss of a hand, in the case of a table saw), and use
them confidently when the circumstances make them the best choice of
tool to solve your problem.

To make a long comment short (too late!!) learn the differences
between 'is' and ==, and use them appropriately.  When I was learning
Python, I found the two books by Mark Lutz to be filled with
information of such things as these.

D

[toc] | [prev] | [next] | [standalone]


#16351

FromEthan Furman <ethan@stoneleaf.us>
Date2011-11-28 12:05 -0800
Message-ID<mailman.3105.1322512513.27778.python-list@python.org>
In reply to#16346
Den wrote:
> With respect, I disagree with advice that the use of a language
> construct should be rare.  All constructs should be used
> *appropriately*.

+1

~Ethan~

[toc] | [prev] | [next] | [standalone]


#16375

Fromalex23 <wuwei23@gmail.com>
Date2011-11-28 19:58 -0800
Message-ID<e4909b58-ae18-4169-ba44-ee9abf8d8260@c16g2000pre.googlegroups.com>
In reply to#16346
On Nov 29, 5:22 am, Den <patents...@gmail.com> wrote:
> On Nov 26, 3:01 pm, Steven D'Aprano <steve
> > That is correct. You probably should rarely use `is`. Apart from testing
> > for None, use of `is` should be rare.
>
> With respect, I disagree with advice that the use of a language
> construct should be rare.  All constructs should be used
> *appropriately*.

Steven didn't say it _shouldn't_ be used, only that it it should be
_rarely_ used. General consensus would be that that is the most
appropriate use of 'is'.

Value comparisons are _far_ more common in Python than identity
comparisons, the ubiquitous None notwithstanding.

But for your general point, I totally agree. I feel the same way about
the ternary syntax, boolean defaults for conditionals etc

[toc] | [prev] | [next] | [standalone]


#16382

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2011-11-29 08:41 +0000
Message-ID<4ed49aba$0$14018$c3e8da3$76491128@news.astraweb.com>
In reply to#16346
On Mon, 28 Nov 2011 11:22:09 -0800, Den wrote:

> With respect, I disagree with advice that the use of a language
> construct should be rare.  All constructs should be used
> *appropriately*.

And if those appropriate conditions are rare, then the use of the 
appropriate construct should also be rare. Since it is rare to need to 
care about identity, use of `is` should be rare too.

This is mostly descriptive statement rather than a prescriptive one: it 
is a fact that use of `is` is much less common than use of ==, and even 
more so if you disregard the obvious case of "x is None". 

I am however being a little prescriptive: if somebody thinks they need to 
care about identity, chances are good -- but not certain -- that they're 
mistaken. In code that gives you the choice between writing `is` and ==, 
it is usually, but not often, a bug to write `is`. The proof of this is 
that in actual, existing code, if you swapped == and `is`, most of the 
code would stop working correctly. 

On the other hand if you actually do need to care about identity, then go 
for it. I'm not saying that caring about identity should be prohibited, 
only that in practice it is uncommon that you will.


> While in general a particular use of a Python construct may be rare, if
> the programmer is involved deeply with that rare use, then it is NOT
> rare to him/her.

Regardless of how common brain surgery might be to a brain surgeon, it is 
rare in general. That's all I'm saying. If you happen to work for a data 
recovery centre, then pulling the disk platter out of a hard disk drive 
might be commonplace to you, nevertheless pulling platters out of disks 
is vanishingly rare: out of tens of thousands of HDDs, perhaps only a few 
dozen will be sent to a recover centre at all.

[...]
> Sorry, you plucked a string of mine.  One does not throw a tool out of
> your tool box because it might be dangerous.  Table saws are incredibly
> dangerous, but in the hands of a skilled operator can be competently and
> safely used to produce beautiful woodwork.  To say *never* use a table
> saw because it's dangerous is silly.

Fortunately, I didn't say "never".

In the case of `is`, one shouldn't avoid using `is` because it is 
dangerous, but merely because it is the wrong thing to use. In the same 
way, the average programmer will rarely need to use the math.sinh and 
math.cosh functions, not because they are bad, evil, or dangerous, but 
because they are used for specialist purposes that most coders would 
never care about. Hell, most coders rarely use the standard trigonometric 
functions sin and cos, let alone the hyperbolic versions! This is not a 
value judgement.

If I, in a misplaced sense of egalitarianism ("Emancipation for maths 
functions! Right on brothers!") decided to use sinh instead of sin 
because they looked and sounded similar, my code would almost certain be 
buggy. Likewise if I decided to use `is` instead of == because in English 
they have similar meanings, my code would probably be buggy too.

Sorry to belabour the point, but we're in violent agreement here <wink>



-- 
Steven

[toc] | [prev] | [next] | [standalone]


#16398

FromDen <patentsvnc@gmail.com>
Date2011-11-29 09:11 -0800
Message-ID<7de6a1b0-299e-468b-9ef2-9809643957a9@t16g2000vba.googlegroups.com>
In reply to#16382
On Nov 29, 12:41 am, Steven D'Aprano <steve
+comp.lang.pyt...@pearwood.info> wrote:
> On Mon, 28 Nov 2011 11:22:09 -0800, Den wrote:
> > With respect, I disagree with advice that the use of a language
> > construct should be rare.  All constructs should be used
> > *appropriately*.
>
> And if those appropriate conditions are rare, then the use of the
> appropriate construct should also be rare. Since it is rare to need to
> care about identity, use of `is` should be rare too.
>
> This is mostly descriptive statement rather than a prescriptive one: it
> is a fact that use of `is` is much less common than use of ==, and even
> more so if you disregard the obvious case of "x is None".
>
> I am however being a little prescriptive: if somebody thinks they need to
> care about identity, chances are good -- but not certain -- that they're
> mistaken. In code that gives you the choice between writing `is` and ==,
> it is usually, but not often, a bug to write `is`. The proof of this is
> that in actual, existing code, if you swapped == and `is`, most of the
> code would stop working correctly.
>
> On the other hand if you actually do need to care about identity, then go
> for it. I'm not saying that caring about identity should be prohibited,
> only that in practice it is uncommon that you will.
>
> > While in general a particular use of a Python construct may be rare, if
> > the programmer is involved deeply with that rare use, then it is NOT
> > rare to him/her.
>
> Regardless of how common brain surgery might be to a brain surgeon, it is
> rare in general. That's all I'm saying. If you happen to work for a data
> recovery centre, then pulling the disk platter out of a hard disk drive
> might be commonplace to you, nevertheless pulling platters out of disks
> is vanishingly rare: out of tens of thousands of HDDs, perhaps only a few
> dozen will be sent to a recover centre at all.
>
> [...]
>
> > Sorry, you plucked a string of mine.  One does not throw a tool out of
> > your tool box because it might be dangerous.  Table saws are incredibly
> > dangerous, but in the hands of a skilled operator can be competently and
> > safely used to produce beautiful woodwork.  To say *never* use a table
> > saw because it's dangerous is silly.
>
> Fortunately, I didn't say "never".
>
> In the case of `is`, one shouldn't avoid using `is` because it is
> dangerous, but merely because it is the wrong thing to use. In the same
> way, the average programmer will rarely need to use the math.sinh and
> math.cosh functions, not because they are bad, evil, or dangerous, but
> because they are used for specialist purposes that most coders would
> never care about. Hell, most coders rarely use the standard trigonometric
> functions sin and cos, let alone the hyperbolic versions! This is not a
> value judgement.
>
> If I, in a misplaced sense of egalitarianism ("Emancipation for maths
> functions! Right on brothers!") decided to use sinh instead of sin
> because they looked and sounded similar, my code would almost certain be
> buggy. Likewise if I decided to use `is` instead of == because in English
> they have similar meanings, my code would probably be buggy too.
>
> Sorry to belabour the point, but we're in violent agreement here <wink>
>
> --
> Steven

((laugh)) Yes, I believe we are.

D

[toc] | [prev] | [next] | [standalone]


#16323

FromJean-Michel Pichavant <jeanmichel@sequans.com>
Date2011-11-28 13:57 +0100
Message-ID<mailman.3094.1322485045.27778.python-list@python.org>
In reply to#16262
candide wrote:
> In which cases should we use the is() function ? The is() function 
> compares identity of objects rather than values so I was wondering in 
> which circumstances comparing identities of objects is really vital.
>
> Examining well reputated Python source code, I realize that is() 
> function is mainly used in the following set form :
>
> spam is None
>
> But how much "spam is None" is different from "spam == None" ?
>
>
>
> is() function makes comparaison of (abstract representation of) 
> adresses of objects in memory. Comparing addresses of objects is a low 
> level feature performed by low level langages such as C but seldom 
> needed in high level languages like Python, isn'it ?
I remember meeting a use case where testing identity is required, when 
you are searching for an instance containing a specific object:

class Someone:
    def __init__(self, name, car):
        self.name = name
        self.car = car

class Car:
    def __init__(self, brand):
        self.brand = brand
    def __eq__(self, other):
        return self.brand == other.brand

people = { 'bob':Someone('bob', Car('chrys')), 'cindy': Someone('cindy', 
Car('Volk')), 'carlos':Someone('carlos', Car('Volk'))}
aCar = people['carlos'].car
print "people owning a Volk car", [ people[ppl].name for ppl in people 
if people[ppl].car == Car('Volk')]
print "people owning Carlos's car", [ people[ppl].name for ppl in people 
if people[ppl].car is aCar]

people owning a Volk car ['carlos', 'cindy']
people owning Carlos's car ['carlos']

JM

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.python


csiph-web