kalsl kalsl - 1 year ago 37
Python Question

tuple of strings "is" comparison behaves inconsistently

I'm confused.

foo = ("empty", 0)
foo[0] is "empty"

Returns False. This seems to be a problem with keyword strings, as "list" fails as well. "empt" and other strings return true. This only seems to happen with tuples, as if foo is a list the code also returns true

I've tested this with python 3.4.3 and python 3.5 and both behave this way, python2.7 doesn't seem to have this issue though and returns true as expected.

Am I missing some standard on tuples in python3? I've attempted to google-foo this problem but am coming up short.

To clear things up, my exact question is why does

foo = ("empty", 0)
foo[0] is "empty

return False, but

foo = ("empt", 0)
foo[0] is "empt"

return True?

Answer Source

As the other answers already mentioned: You are comparing strings by identity and this is likely to fail. Assumptions about the identity of string literals can not be made.

However, you actually found a subtle issue.

>>> t = ("list",); t[0] is "list"
>>> t = ("notlist",); t[0] is "notlist"
>>> t = ("list",)
>>> id(t[0])
>>> id("list")
>>> t[0] is "list"
>>> l = ("notlist",)
>>> id(l[0])
>>> id("notlist")
>>> l[0] is "notlist"
# interestingly, this works:
>>> ("list",)[0] is "list"

(Tested with Python 3.5.1+ interactive shell)

This is plainly implementation-dependent behavior by some component of python, presumably lexer or parser.

Bottom-line: Use == for string comparison, as long as you do not depend on object identity.