Відповіді:
Ви можете скористатися in
оператором :
if "blah" not in somestring:
continue
TypeError: argument of type 'NoneType' is not iterable
in
оператор Python для алгоритму Rabin-Carp?
Якщо це просто пошук підрядка, який ви можете використовувати 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
. Це може бути або не бути тим, що ви хочете.
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 рядок містить метод підрядки?
Так, але Python має оператор порівняння, який ви повинні використовувати замість цього, оскільки мова має намір використовувати його, а інші програмісти очікують, що ви будете ним користуватися. Це ключове слово in
, яке використовується в якості оператора порівняння:
>>> 'foo' in '**foo**'
True
Протилежністю (доповненням), яку задає оригінальне запитання, є not in
:
>>> 'foo' not in '**foo**' # returns False
False
Це семантично те саме, що є, not 'foo' in '**foo**'
але набагато читабельніше і чітко передбачено мовою як поліпшення читабельності.
__contains__
, find
іindex
Як було обіцяно, ось такий contains
метод:
str.__contains__('**foo**', 'foo')
повертає True
. Ви також можете викликати цю функцію з екземпляра суперструни:
'**foo**'.__contains__('foo')
Але не варто. Методи, які починаються з підкреслення, вважаються семантично приватними. Єдина причина використовувати це при розширенні in
та not in
функціональності (наприклад, якщо підкласифікація str
):
class NoisyString(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
оператор порівняння.
Ми можемо порівняти різні способи досягнення однієї і тієї ж мети.
import timeit
def in_(s, other):
return other in s
def contains(s, other):
return s.__contains__(other)
def find(s, other):
return s.find(other) != -1
def index(s, other):
try:
s.index(other)
except ValueError:
return False
else:
return True
perf_dict = {
'in:True': min(timeit.repeat(lambda: in_('superstring', 'str'))),
'in:False': min(timeit.repeat(lambda: in_('superstring', 'not'))),
'__contains__:True': min(timeit.repeat(lambda: contains('superstring', 'str'))),
'__contains__:False': min(timeit.repeat(lambda: contains('superstring', 'not'))),
'find:True': min(timeit.repeat(lambda: find('superstring', 'str'))),
'find:False': min(timeit.repeat(lambda: find('superstring', 'not'))),
'index:True': min(timeit.repeat(lambda: index('superstring', 'str'))),
'index:False': min(timeit.repeat(lambda: index('superstring', 'not'))),
}
І тепер ми бачимо, що використання in
набагато швидше, ніж інші. Менше часу на еквівалентну операцію краще:
>>> perf_dict
{'in:True': 0.16450627865128808,
'in:False': 0.1609668098178645,
'__contains__:True': 0.24355481654697542,
'__contains__:False': 0.24382793854783813,
'find:True': 0.3067379407923454,
'find:False': 0.29860888058124146,
'index:True': 0.29647137792585454,
'index:False': 0.5502287584545229}
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#L153
if needle in haystack:
це нормальне використання, як каже @Michael - воно покладається на in
оператора, читабельніше та швидше, ніж виклик методу.
Якщо вам справді потрібен метод замість оператора (наприклад, зробити якийсь дивний key=
для дуже своєрідного роду ...?), Це було б 'haystack'.__contains__
. Але оскільки ваш приклад використовується для використання в if
, я думаю, ви насправді не маєте на увазі те, що ви говорите ;-). Недоцільно (ні читати, ні ефективно) використовувати спеціальні методи безпосередньо - вони призначені для використання натомість через оператори та вбудовані модулі, які делегують їм.
in
Рядки та списки PythonОсь кілька корисних прикладів, які говорять самі про 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]
Caveat. Списки є ітерабельними, а in
метод діє на ітерабелі, а не лише на рядки.
["bar", "foo", "foobar"] in "foof"
:?
Якщо ви задоволені, "blah" in somestring
але хочете, щоб це був виклик функції / методу, ви, ймовірно, можете це зробити
import operator
if not operator.contains(somestring, "blah"):
continue
Усі оператори в Python можуть бути більш-менш знайдені в операторському модулі, включаючи in
.
Тому, мабуть, немає нічого подібного для векторного порівняння. Очевидним способом Python це було б:
names = ['bob', 'john', 'mike']
any(st in 'bob and john' for st in names)
>> True
any(st in 'mary and jane' for st in names)
>> False
in
застосовувати зі списками, оскільки це робить лінійне сканування елементів і порівняно повільне. Замість цього використовуйте набір, особливо якщо тести на членство потрібно робити неодноразово.
Можна використовувати y.count()
.
Він поверне ціле значення кількості разів, коли в рядку з'являється підряд.
Наприклад:
string.count("bah") >> 0
string.count("Hello") >> 1
Ось ваша відповідь:
if "insert_char_or_string_here" in "insert_string_to_search_here":
#DOSTUFF
Щоб перевірити, чи неправдиво:
if not "insert_char_or_string_here" in "insert_string_to_search_here":
#DOSTUFF
АБО:
if "insert_char_or_string_here" not in "insert_string_to_search_here":
#DOSTUFF
__contains__(self, item)
,__iter__(self)
і__getitem__(self, key)
в цьому порядку визначати, чи лежить елемент у заданому вмісті. Реалізуйте принаймні один із цих методів, щоб зробитиin
доступними для вашого власного типу.