Оператор "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)