Под капотом Python будет использовать __contains__(self, item), __iter__(self)и __getitem__(self, key)в этом порядке, чтобы определить, находится ли элемент в данном содержимом. Реализуйте хотя бы один из этих методов, чтобы сделать его inдоступным для вашего пользовательского типа.
BallpointBen
28
Просто убедитесь, что не будет None. В противном случае вы получитеTypeError: argument of type 'NoneType' is not iterable
Большая тыква
6
FWIW, это идиоматический способ достижения указанной цели.
Трентон
7
Для строк использует ли inоператор Python алгоритм Рабина-Карпа?
Сэм Чаты
4
@SamChats см stackoverflow.com/questions/18139660/... для деталей реализации (в CPython, AFAIK спецификация языка не предписывает какой - либо конкретный алгоритм здесь).
Кристоф Буршка
667
Если это просто поиск по подстроке, вы можете использовать string.find("substring").
Вы должны быть немного осторожным с find, indexи inхотя, как они поиск подстрок. Другими словами, это:
s ="This be a string"if s.find("is")==-1:print("No 'is' here!")else:print("Found 'is' in the string.")
Точно Found 'is' in the string.так же вывел if "is" in s:бы, оценил бы True. Это может или не может быть то, что вы хотите.
+1 за выделение ошибок, связанных с поиском подстроки. очевидное решение состоит в том, if ' is ' in s:который вернется так, Falseкак (вероятно) ожидается.
Ааронастерлинг
95
@aaronasterling Очевидно, что это может быть, но не совсем правильно. Что если у вас есть пунктуация или она в начале или в конце? Как насчет капитализации? Лучше было бы поиск по регулярному выражению без учета регистра \bis\b(границы слова).
Боб
2
@JamieBull Еще раз, вы должны подумать, если вы хотите включить пунктуацию в качестве разделителя для слова. Расщепление будет иметь в значительной степени тот же эффект, что и наивное решение проверки ' is ', в частности, оно не поймает This is, a comma'или 'It is.'.
Боб
7
@JamieBull: я очень сомневаюсь, что реальное разделение входных данных s.split(string.punctuation + string.whitespace)разделит хотя бы один раз; splitэто не то же самое, что семейство функций strip/ rstrip/ lstrip, он разделяется только тогда, когда видит все символы-разделители, непрерывно, в том же порядке. Если вы хотите разделить классы символов, вы вернетесь к регулярным выражениям (в этот момент поиск r'\bis\b'без разделения - более простой и быстрый путь).
ShadowRanger
8
'is' not in (w.lower() for w in s.translate(string.maketrans(' ' * len(string.punctuation + string.whitespace), string.punctuation + string.whitespace)).split()- Хорошо, точка взята. Теперь это смешно ...
Джейми Булл,
190
Есть ли в Python строка, содержащая метод подстроки?
Да, но в Python есть оператор сравнения, который вы должны использовать вместо этого, потому что язык предполагает его использование, и другие программисты будут ожидать, что вы будете его использовать. Это ключевое слово in, которое используется в качестве оператора сравнения:
>>>'foo'in'**foo**'True
Противоположность (дополнение), о которой просит исходный вопрос not in:
>>>'foo'notin'**foo**'# returns FalseFalse
Семантически это то же самое, not 'foo' in '**foo**'что и гораздо более читабельно и явно предусмотрено в языке как улучшение читаемости.
Избегайте использования __contains__, findиindex
Как и было обещано, вот containsметод:
str.__contains__('**foo**','foo')
возвращается True. Вы также можете вызвать эту функцию из экземпляра суперструны:
'**foo**'.__contains__('foo')
Но не надо. Методы, которые начинаются с подчеркивания, считаются семантически закрытыми. Единственная причина , чтобы использовать это при расширении inи not inфункциональные возможности (например , если подклассов str):
classNoisyString(str):def __contains__(self, other):print('testing if "{0}" in "{1}"'.format(other, self))return super(NoisyString, self).__contains__(other)
ns =NoisyString('a string with a substring inside')
и сейчас:
>>>'substring'in ns
testing if"substring"in"a string with a substring inside"True
Также избегайте следующих строковых методов:
>>>'**foo**'.index('foo')2>>>'**foo**'.find('foo')2>>>'**oo**'.find('foo')-1>>>'**oo**'.index('foo')Traceback(most recent call last):File"<pyshell#40>", line 1,in<module>'**oo**'.index('foo')ValueError: substring not found
Другие языки могут не иметь методов для непосредственного тестирования подстрок, и поэтому вам придется использовать эти типы методов, но с Python гораздо эффективнее использовать inоператор сравнения.
Сравнение производительности
Мы можем сравнить различные способы достижения одной и той же цели.
Почему следует избегать str.indexи str.find? Как еще вы могли бы предложить кому-то найти индекс подстроки вместо того, существует ли он или нет? (или вы имели в виду избегать их использования s.find(ss) != -1вместо ss in s
содержимого
3
Именно так, хотя цель использования этих методов может быть лучше решена путем элегантного использования reмодуля. Я еще не нашел использования str.index или str.find себя ни в одном коде, который я написал.
Аарон Холл
Пожалуйста, распространите свой ответ на совет против использования str.count( string.count(something) != 0). дрожь
if needle in haystack:как говорит @Michael, это обычное использование - оно опирается на inоператор, более читабельное и более быстрое, чем вызов метода.
Если вам действительно нужен метод вместо оператора (например, чтобы сделать какой-то странный key=для очень своеобразного рода ...?), Это было бы 'haystack'.__contains__. Но так как ваш пример для использования в if, я думаю, вы на самом деле не имеете в виду то, что говорите ;-). Непригодно (ни читабельно, ни эффективно) напрямую использовать специальные методы - они предназначены для использования вместо них через операторы и встроенные функции, которые им делегируют.
Вот несколько полезных примеров, которые говорят сами за себя относительно inметода:
"foo"in"foobar"True"foo"in"Foobar"False"foo"in"Foobar".lower()True"foo".capitalize()in"Foobar"True"foo"in["bar","foo","foobar"]True"foo"in["fo","o","foobar"]False["foo"in a for a in["fo","o","foobar"]][False,False,True]
Предостережение. Списки являются итеративными, а inметод действует на итерируемые, а не только на строки.
Можно ли переключить итеративный список для поиска любого списка в одной строке? Пример: ["bar", "foo", "foobar"] in "foof"?
CaffeinatedCoder
1
@CaffeinatedCoder, нет, это требует вложенной итерации. Лучше всего это сделать, объединив список с помощью каналов "|" .join (["bar", "foo", "foobar"]) и скомпилировав из него регулярное выражение, а затем сопоставив его с "foof"
firelynx
2
любой ([x в "foof" для x в ["bar", "foo", "foobar"]])
Исаак Вайс
1
@IzaakWeiss Ваш один вкладыш работает, но он не очень читабелен и выполняет вложенные итерации. Я бы посоветовал не делать этого
firelynx
1
@ PiyushS. Что вы подразумеваете под сложностью? «WTF / мин» намного выше с регулярным выражением.
firelynx
42
Если вы довольны, "blah" in somestringно хотите, чтобы это был вызов функции / метода, вы, вероятно, можете сделать это
Это потому, что существует множество способов создания Продукта из атомарных переменных. Вы можете поместить их в кортеж, список (которые являются формами декартовых произведений и имеют подразумеваемый порядок), или они могут быть названы свойствами класса (без априорного порядка) или значениями словаря, или они могут быть файлами в каталог или что-то еще. Всякий раз, когда вы можете однозначно идентифицировать (iter или getitem) что-либо в «контейнере» или «контексте», вы можете видеть этот «контейнер» как своего рода вектор и определять двоичные операции для него. en.wikipedia.org/wiki/…
Нириэль
Ничего inне стоит использовать со списками, потому что он выполняет линейное сканирование элементов и сравнивается медленно. Вместо этого используйте набор, особенно если тесты на членство должны выполняться повторно.
cs95
22
Вы можете использовать y.count().
Он вернет целочисленное значение числа раз, когда подстрока появляется в строке.
подсчет строки стоит дорого, если вы просто хотите проверить, есть ли она ...
Жан-Франсуа Фабр
3
методы, которые существуют в оригинальном посте от 2010 года, поэтому я закончил редактировать их, с консенсусом сообщества (см. мета-пост meta.stackoverflow.com/questions/385063/… )
Жан-Франсуа Фабр
17
нет. Я хочу сказать: «Почему отвечать так же, как другие 9 лет назад»?
затем, если у вас есть полномочия удалить его, удалите его, в противном случае сделайте то, что должны, и продолжайте. ИМО этот ответ добавляет ценность, что отражается в положительных откликах пользователей.
__contains__(self, item)
,__iter__(self)
и__getitem__(self, key)
в этом порядке, чтобы определить, находится ли элемент в данном содержимом. Реализуйте хотя бы один из этих методов, чтобы сделать егоin
доступным для вашего пользовательского типа.TypeError: argument of type 'NoneType' is not iterable
in
оператор Python алгоритм Рабина-Карпа?Если это просто поиск по подстроке, вы можете использовать
string.find("substring")
.Вы должны быть немного осторожным с
find
,index
иin
хотя, как они поиск подстрок. Другими словами, это:Точно
Found 'is' in the string.
так же вывелif "is" in s:
бы, оценил быTrue
. Это может или не может быть то, что вы хотите.источник
if ' is ' in s:
который вернется так,False
как (вероятно) ожидается.\bis\b
(границы слова).' is '
, в частности, оно не поймаетThis is, a comma'
или'It is.'
.s.split(string.punctuation + string.whitespace)
разделит хотя бы один раз;split
это не то же самое, что семейство функцийstrip
/rstrip
/lstrip
, он разделяется только тогда, когда видит все символы-разделители, непрерывно, в том же порядке. Если вы хотите разделить классы символов, вы вернетесь к регулярным выражениям (в этот момент поискr'\bis\b'
без разделения - более простой и быстрый путь).'is' not in (w.lower() for w in s.translate(string.maketrans(' ' * len(string.punctuation + string.whitespace), string.punctuation + string.whitespace)).split()
- Хорошо, точка взята. Теперь это смешно ...Да, но в Python есть оператор сравнения, который вы должны использовать вместо этого, потому что язык предполагает его использование, и другие программисты будут ожидать, что вы будете его использовать. Это ключевое слово
in
, которое используется в качестве оператора сравнения:Противоположность (дополнение), о которой просит исходный вопрос
not in
:Семантически это то же самое,
not 'foo' in '**foo**'
что и гораздо более читабельно и явно предусмотрено в языке как улучшение читаемости.Избегайте использования
__contains__
,find
иindex
Как и было обещано, вот
contains
метод:возвращается
True
. Вы также можете вызвать эту функцию из экземпляра суперструны:Но не надо. Методы, которые начинаются с подчеркивания, считаются семантически закрытыми. Единственная причина , чтобы использовать это при расширении
in
иnot in
функциональные возможности (например , если подклассовstr
):и сейчас:
Также избегайте следующих строковых методов:
Другие языки могут не иметь методов для непосредственного тестирования подстрок, и поэтому вам придется использовать эти типы методов, но с Python гораздо эффективнее использовать
in
оператор сравнения.Сравнение производительности
Мы можем сравнить различные способы достижения одной и той же цели.
И теперь мы видим, что использование
in
намного быстрее, чем другие. Лучше меньше времени на выполнение эквивалентной операции:источник
str.index
иstr.find
? Как еще вы могли бы предложить кому-то найти индекс подстроки вместо того, существует ли он или нет? (или вы имели в виду избегать их использованияs.find(ss) != -1
вместоss in s
re
модуля. Я еще не нашел использования str.index или str.find себя ни в одном коде, который я написал.str.count
(string.count(something) != 0
). дрожьoperator
версия модуля ?in_
выше - но со стековым фреймом вокруг него, поэтому оно медленнее: github.com/python/cpython/blob/3.7/Lib/operator.py#L153if needle in haystack:
как говорит @Michael, это обычное использование - оно опирается наin
оператор, более читабельное и более быстрое, чем вызов метода.Если вам действительно нужен метод вместо оператора (например, чтобы сделать какой-то странный
key=
для очень своеобразного рода ...?), Это было бы'haystack'.__contains__
. Но так как ваш пример для использования вif
, я думаю, вы на самом деле не имеете в виду то, что говорите ;-). Непригодно (ни читабельно, ни эффективно) напрямую использовать специальные методы - они предназначены для использования вместо них через операторы и встроенные функции, которые им делегируют.источник
in
Python строки и спискиВот несколько полезных примеров, которые говорят сами за себя относительно
in
метода:Предостережение. Списки являются итеративными, а
in
метод действует на итерируемые, а не только на строки.источник
["bar", "foo", "foobar"] in "foof"
?Если вы довольны,
"blah" in somestring
но хотите, чтобы это был вызов функции / метода, вы, вероятно, можете сделать этоВсе операторы в Python могут быть более или менее найдены в модуле оператора, включая
in
.источник
Поэтому, очевидно, нет ничего похожего для векторного сравнения. Очевидный способ сделать это на Python:
источник
in
не стоит использовать со списками, потому что он выполняет линейное сканирование элементов и сравнивается медленно. Вместо этого используйте набор, особенно если тесты на членство должны выполняться повторно.Вы можете использовать
y.count()
.Он вернет целочисленное значение числа раз, когда подстрока появляется в строке.
Например:
источник
Вот ваш ответ:
Для проверки, является ли это ложным:
ИЛИ:
источник
Вы можете использовать регулярные выражения, чтобы получить вхождения:
источник