Оператор "IN" с пустыми строками в Python 3.0

Поскольку я читаю руководства по Python 3, я натолкнулся на следующее:

>>> '' in 'spam'
True

Я понимаю, что '' не имеет пробелов.

Когда я пытаюсь выполнить следующий вывод оболочки, я получаю вывод, показанный ниже:

>>> '' in ' spam '
True

Кто-нибудь может помочь объяснить, что происходит?

Ответ 1

'' - пустая строка, такая же, как "". Пустая строка - это подстрока любой другой строки.

Когда a и b являются строками, выражение a in b проверяет, что a является подстрокой b. То есть последовательность символов a должна существовать в b; должен быть индекс i такой, что b[i:i+len(a)] == a. Если a пусто, то любой индекс i удовлетворяет этому условию.

Это не означает, что когда вы перейдете на b, вы получите a. В отличие от других последовательностей, в то время как каждый элемент, созданный for a in b, удовлетворяет a in b, a in b не означает, что a будет производиться путем итерации над b.

Итак '' in x и "" in x возвращает True для любой строки x:

>>> '' in 'spam'
True
>>> "" in 'spam'
True
>>> "" in ''
True
>>> '' in ""
True
>>> '' in ''
True
>>> '' in ' ' 
True
>>> "" in " "
True

Ответ 2

строковый литерал '' представляет пустую строку. Это в основном строка с длиной нуля, которая не содержит символов.

Оператор in определяется для последовательностей для возврата "True, если элемент s равен x, else False" для выражения x in s. Для общих последовательностей это означает, что один из элементов в s (обычно доступный с помощью итерации) равен тестируемому элементу x. Однако для строк оператор in имеет семантику подпоследовательности. Итак, x in s истинно, когда x является подстрокой s.

Формально это означает, что для подстроки x с длиной n должен быть индекс i, который удовлетворяет следующему выражению: s[i:i+n] == x.

Это легко понять с помощью примера:

>>> s = 'foobar'

>>> x = 'foo'
>>> n = len(x) # 3
>>> i = 0
>>> s[i:i+n] == x
True

>>> x = 'obar'
>>> n = len(x) # 4
>>> i = 2
>>> s[i:i+n] == x
True

Алгоритмически то, что должен сделать оператор in (или базовый метод __contains__), - это перебрать i на все возможные значения (0 <= i < len(s) - n) и проверить, истинно ли условие для любого i.

Возвращаясь к пустой строке, становится ясно, почему проверка '' in s истинна для каждой строки s: n равна нулю, поэтому мы проверяем s[i:i]; и это пустая строка для каждого допустимого индекса i:

>>> s[0:0]
''
>>> s[1:1]
''
>>> s[2:2]
''

Верно даже, что s является самой пустой строкой, потому что упорядочение последовательности определено для возврата пустой последовательности, когда задан диапазон вне последовательности (вот почему вы могли сделать s[74565463:74565469] на коротких строках).

Итак, это объясняет, почему проверка сдерживания с помощью in всегда возвращает True при проверке пустой строки как подстроки. Но даже если вы думаете об этом логически, вы можете увидеть причину: Подстрока является частью строки, которую вы можете найти в другой строке. Однако пустую строку можно найти между двумя символами. Как будто вы можете добавить бесконечное количество нулей в число, вы можете добавить бесконечное количество пустых строк в строку без фактической модификации этой строки.

Ответ 3

Как указывает Раши Панчал, оператор включения in следует за теоретико-множественным соглашением и предполагает, что пустая строка является подстрокой любой строки.

Вы можете попытаться убедить себя, почему это имеет смысл, рассматривая следующее: пусть s будет такой строкой, что '' in s == False. Тогда '' in s[len(s):] лучше быть ложным транзитивностью (или существует подмножество s, содержащее '', но s не содержит '' и т.д.). Но тогда '' in '' == False, что тоже не очень велико. Таким образом, вы не можете выбрать любую строку s, такую, что '' not in s, которая не создает проблемы.

Конечно, когда возникают сомнения, имитируйте это:

s = input('Enter any string you dare:\n')

print('' in '')
print(s == s + '' == '' + s)
print('' in '' + s)