2

This might be a very elementary question and I should know this but how does the following line evaluate to true?

>>> '' in 'spam'
True

Why/How is the empty string/character in a non-empty string? I tried this in Idle for Python 2.7 and it's evaluating to true. I found this from the link to Automate the Boring Stuff chapter 6

Classified
  • 5,759
  • 18
  • 68
  • 99
  • 2
    `print( 'spam'[:0])` or `print(repr('spam'[:0]))` might make it more obvious – Padraic Cunningham Dec 01 '15 at 23:36
  • 1
    another dupe http://stackoverflow.com/questions/27603885/why-python-returns-true-when-checking-if-an-empty-string-is-in-another – Padraic Cunningham Dec 01 '15 at 23:37
  • 1
    @PadraicCunningham `[][:0] == []` yet `[] in []` is False. Similarly, `list('spam')[:0] == []` but `[] not in list('spam')`. – Two-Bit Alchemist Dec 01 '15 at 23:43
  • @PadraicCunningham - thx for the tip and the link to the duplicate question. :-) I just tried and it was a blank :-) – Classified Dec 01 '15 at 23:43
  • 1
    @Two-BitAlchemist, `list('spam')[:0]` is accessing a list not the string, there is no empty list in the list, the list itself is empty. – Padraic Cunningham Dec 01 '15 at 23:45
  • @PadraicCunningham That's what I meant to show. Strings can be thought of as lists of characters. In other languages it is explicitly this way. Yet "real" lists do not behave in this way that you describe is "obvious" for strings. – Two-Bit Alchemist Dec 01 '15 at 23:50
  • @PadraicCunningham Exactly equivalent to the argument in your edited comment is "There is no empty string in the string; the string itself is empty." Yet `'' in ''` and this, according at least to you, is "obvious". – Two-Bit Alchemist Dec 01 '15 at 23:52
  • 1
    @Two-BitAlchemist, `' ' in ' ' -> True` `"foo" in "foo" True` `["foo"] in ["foo"] 0> False`, the behaviour is the same for empty and non-empty strings as the behaviour for lists also stays the same between empty and non-empty – Padraic Cunningham Dec 01 '15 at 23:58
  • 2
    @PadraicCunningham Yes, strings are great like that in Python. Sometimes they behave like a character and sometimes like a string. There's a broader conceptual question here, and perhaps the majority of mathematicians and programmers think one way; but it's not obvious, it's taught. A string is an ordered sequence of characters (uncontroversial). The empty string is in every string including itself (largely uncontroversial though I am balking at it now). I challenge you to think of another ordered sequence of literally anything where we think about the empty version of it this way. – Two-Bit Alchemist Dec 02 '15 at 00:10
  • @Two-BitAlchemist, to me it makes perfect sense in the context of how string behaves in python but then again I seem to be one of the minority that is completely unenamoured by the logic of tuples work, in particular a single element tuple, how anyone thought letting `(1)` or `1` create an int and `(1,)` or `1,` creates a tuple truly baffles me. I have gotten nailed by that countless times. – Padraic Cunningham Dec 02 '15 at 00:21
  • 1
    @Classified I researched the theoretical side of your question last night (why we think of strings this way as opposed to why they behave this particular way in Python), and I think the best answer is touched on by [Jon Skeet's answer here](http://stackoverflow.com/a/145516/2588818). I still think it's a bit arbitrary either way, whether you consider `''` to be in every string or not, but it's a consequence of most normal string implementations that it is. – Two-Bit Alchemist Dec 02 '15 at 14:54
  • 1
    @Two-BitAlchemist, thanks for finding that answer and for discussing with Padraic. i didn't think my question could be interpreted as a theoretical one :) – Classified Dec 03 '15 at 00:37

1 Answers1

3

Because the in operator is to test membership, and by that notion, the empty set is a subset of all other sets. To be consistent in that regard, the in operator was deliberately designed to act accordingly.

5.9 Comparisons

The operators in and not in test for collection membership. x in s evaluates to true if x is a member of the collection s, and false otherwise. x not in s returns the negation of x in s. The collection membership test has traditionally been bound to sequences; an object is a member of a collection if the collection is a sequence and contains an element equal to that object. However, it make sense for many other object types to support membership tests without being a sequence. In particular, dictionaries (for keys) and sets support membership testing.

For the list and tuple types, x in y is true if and only if there exists an index i such that x == y[i] is true.

For the Unicode and string types, x in y is true if and only if x is a substring of y. An equivalent test is y.find(x) != -1. Note, x and y need not be the same type; consequently, u'ab' in 'abc' will return True. Empty strings are always considered to be a substring of any other string, so "" in "abc" will return True.

Community
  • 1
  • 1
Cory Kramer
  • 114,268
  • 16
  • 167
  • 218