From: Stefan Schwarzer on 6 Aug 2010 09:37 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
From: Peter Pearson on 6 Aug 2010 13:20 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.
From: Terry Reedy on 6 Aug 2010 14:20 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
From: Stefan Schwarzer on 6 Aug 2010 14:36 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
From: Ethan Furman on 6 Aug 2010 15:34
Stefan Schwarzer wrote: > 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 Instead of using 'is' use '=='. Maybe not as cute, but definitely more robust! ~Ethan~ |