Odpowiedzi:
Możesz użyć inoperatora :
if "blah" not in somestring:
continue
TypeError: argument of type 'NoneType' is not iterable
inoperator Python używa algorytmu Rabin-Carp?
Jeśli jest to tylko wyszukiwanie podciągów, możesz użyć string.find("substring").
Trzeba być trochę ostrożny z find, indexi inchoć są one podciąg wyszukiwania. Innymi słowy, to:
s = "This be a string"
if s.find("is") == -1:
print("No 'is' here!")
else:
print("Found 'is' in the string.")
Wypisałby się Found 'is' in the string.podobnie, if "is" in s:oceniałby True. To może być lub nie być to, czego chcesz.
if ' is ' in s:co powróci, Falsejak się spodziewano (prawdopodobnie).
\bis\b(granice słów).
' is ', w szczególności, że nie zostanie on złapany This is, a comma'lub 'It is.'.
s.split(string.punctuation + string.whitespace)choć raz; splitnie jest jak rodzina funkcji strip/ rstrip/ lstrip, dzieli się tylko wtedy, gdy widzi wszystkie znaki separatora, w sposób ciągły, w dokładnie takiej kolejności. Jeśli chcesz podzielić na klasy znaków, wrócisz do wyrażeń regularnych (w tym momencie wyszukiwanie r'\bis\b'bez podziału jest łatwiejszą i szybszą drogą).
'is' not in (w.lower() for w in s.translate(string.maketrans(' ' * len(string.punctuation + string.whitespace), string.punctuation + string.whitespace)).split()- ok, punkt wzięty. To jest teraz śmieszne ...
Czy Python ma ciąg zawierający metodę podciągów?
Tak, ale Python ma operator porównania, którego należy użyć zamiast tego, ponieważ język zamierza go używać, a inni programiści oczekują, że będziesz go używać. To słowo kluczowe jest inużywane jako operator porównania:
>>> 'foo' in '**foo**'
True
Przeciwnie (uzupełnienie), o które prosi pierwotne pytanie, jest not in:
>>> 'foo' not in '**foo**' # returns False
False
Jest to semantycznie to samo, not 'foo' in '**foo**'ale o wiele bardziej czytelne i wyraźnie przewidziane w języku jako poprawa czytelności.
__contains__, findorazindexZgodnie z obietnicą, oto containsmetoda:
str.__contains__('**foo**', 'foo')
zwraca True. Możesz także wywołać tę funkcję z instancji superstringu:
'**foo**'.__contains__('foo')
Ale nie rób tego. Metody rozpoczynające się od podkreślenia są uważane za semantycznie prywatne. Jedynym powodem, dla którego można to wykorzystać, jest rozszerzenie funkcji ini not in(np. W przypadku podklasy 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')
i teraz:
>>> 'substring' in ns
testing if "substring" in "a string with a substring inside"
True
Unikaj również następujących metod ciągu:
>>> '**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
Inne języki mogą nie mieć żadnych metod bezpośredniego testowania podciągów, więc musisz użyć tego rodzaju metod, ale w Pythonie znacznie bardziej wydajne jest użycie inoperatora porównania.
Możemy porównać różne sposoby osiągnięcia tego samego celu.
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'))),
}
A teraz widzimy, że używanie injest znacznie szybsze niż inne. Im mniej czasu na wykonanie równoważnej operacji, tym lepiej:
>>> 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.indexi str.find? Jak inaczej zasugerowałbyś komuś znalezienie indeksu podciągów zamiast tego, czy istnieje? (czy miałeś na myśli unikanie ich zamiast zawiera - więc nie używaj s.find(ss) != -1zamiast ss in s?)
remodułu. Nie znalazłem jeszcze zastosowania dla str.index lub str.find siebie w żadnym kodzie, który napisałem.
str.countrównież ( string.count(something) != 0). Dreszcz
operatorwersja modułu ?
in_powyżej - ale z ramką stosu, więc jest wolniejszy: github.com/python/cpython/blob/3.7/Lib/operator.py#L153
if needle in haystack:jest normalnym zastosowaniem, jak mówi @Michael - zależy od inoperatora, jest bardziej czytelny i szybszy niż wywołanie metody.
Jeśli naprawdę potrzebujesz metody zamiast operatora (np. Aby zrobić coś dziwnego key=dla bardzo osobliwego rodzaju ...?), Byłoby to możliwe 'haystack'.__contains__. Ale ponieważ twój przykład jest przeznaczony do użycia if, myślę, że tak naprawdę nie masz na myśli tego, co mówisz ;-). Nie jest dobrą formą (ani czytelną, ani wydajną) używanie specjalnych metod bezpośrednio - są one przeznaczone do użycia przez operatorów i wbudowane w nie funkcje, które je delegują.
in Ciągi i listy w języku PythonOto kilka przydatnych przykładów, które mówią same za siebie w odniesieniu do inmetody:
"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]
Zastrzeżenie Listy są iterowalne, a inmetoda działa na iterowalne, a nie tylko na ciągi znaków.
["bar", "foo", "foobar"] in "foof"?
Jeśli jesteś zadowolony, "blah" in somestringale chcesz, aby było to wywołanie funkcji / metody, prawdopodobnie możesz to zrobić
import operator
if not operator.contains(somestring, "blah"):
continue
Wszystkich operatorów w Pythonie można mniej więcej znaleźć w module operatora, w tym in.
Najwyraźniej więc nie ma nic podobnego w porównaniu wektorowym. Oczywistym sposobem na zrobienie tego byłoby:
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
inczego nie należy używać z listami, ponieważ wykonuje liniowy skan elementów i jest powolny w porównaniu. Zamiast tego użyj zestawu, szczególnie jeśli testy członkostwa mają być powtarzane.
Możesz użyć y.count().
Zwraca wartość całkowitą liczby przypadków, gdy podciąć pojawia się w ciągu.
Na przykład:
string.count("bah") >> 0
string.count("Hello") >> 1
Oto twoja odpowiedź:
if "insert_char_or_string_here" in "insert_string_to_search_here":
#DOSTUFF
Aby sprawdzić, czy jest to fałsz:
if not "insert_char_or_string_here" in "insert_string_to_search_here":
#DOSTUFF
LUB:
if "insert_char_or_string_here" not in "insert_string_to_search_here":
#DOSTUFF
__contains__(self, item),__iter__(self)iw__getitem__(self, key)tej kolejności, aby ustalić, czy element leży w danym zawiera. Zaimplementuj co najmniej jedną z tych metod, abyinudostępnić niestandardowy typ.