[Tutor] Looks like a judgment bug.

Steven D'Aprano steve at pearwood.info
Fri Apr 12 03:10:03 CEST 2013


On 11/04/13 20:41, w qj wrote:
> I found this under Windows Python3
>>>> l="http://f/"
>>>> l[-1] is not '/'
> False
>>>>
>
> and this under Linux Python3
>>>> l = "http://ff.f/"
>>>> l[-1]
> '/'
>>>> l[-1] is not '/'
> True
>
> It's Looks like a python bug?



No, it is a bug in your understanding. The "is" and "is not" operators are for testing object identity, not equality. Python makes very few promises about object identity, and in this case both examples are fine. When you write this code:


l[-1] is not '/'  # where l[-1] == '/'


how does Python evaluate this expression?

First, it looks up l[-1], which creates a new object equal to the single-character string '/'. Then, Python evaluates the literal '/'. Now it has a choice: it might *reuse* the object that was just created a microsecond ago, or it might create a *new* object with the same value. Both behaviours are allowed, the language does not specify one or the other.

In the first case, you get one object referenced twice, and "is not" returns False. In the second case, you get two distinct objects referenced once each, and "is not" returns True. Both behaviours are correct, since Python doesn't promise when it will or won't create a new object in cases like this.

Whether Python creates two distinct objects or not will depend on the version of Python you use, the implementation, the operating system, possibly even the day of the week. (Well, probably not the last one, but it *could*.) No promises are made, and you cannot rely on one behaviour or the other.

You almost never need to use object identity, and should nearly always use == and != instead. Almost the only exception is when testing for the None singleton object.

# if one of the values is None, always use "is" or "is not":
if x is None

# for everything else, always use == or !=
x == '/'


There are some other exceptions, but they are rare.


For interest, I ran this expression under various different versions of Python:

print ('http://f/'[-1] is '/')


And these are the results I got:

Jython 2.5: False
IronPython 2.6: False
CPython:
   1.5: True
   2.4: True
   2.5: True
   2.6: True
   2.7: True
   3.1: False
   3.2: False
   3.3: True


Unless you have the exact same versions, built with the exact same compiler, on the exact same operating systems, you may get different results.




-- 
Steven


More information about the Tutor mailing list