Risposte:
Puoi usare l' in
operatore :
if "blah" not in somestring:
continue
TypeError: argument of type 'NoneType' is not iterable
in
operatore Python utilizza l'algoritmo Rabin-Carp?
Se è solo una ricerca di sottostringa che puoi usare string.find("substring")
.
Non c'è bisogno di essere un po 'attenti con find
, index
e in
anche se, come essi sono SUBSTRING ricerche. In altre parole, questo:
s = "This be a string"
if s.find("is") == -1:
print("No 'is' here!")
else:
print("Found 'is' in the string.")
Stamperebbe allo Found 'is' in the string.
stesso modo, if "is" in s:
valuterebbe a True
. Questo può o meno essere quello che vuoi.
if ' is ' in s:
che tornerà False
come è (probabilmente) previsto.
\bis\b
(limiti di parole).
' is '
, in particolare, non catturerà This is, a comma'
o 'It is.'
.
s.split(string.punctuation + string.whitespace)
si dividerebbe anche una volta; split
non è come la strip
/ rstrip
/ lstrip
famiglia di funzioni, si divide solo quando vede tutti i caratteri delimitatori, contigui, nell'ordine esatto. Se vuoi dividere in classi di personaggi, sei tornato alle espressioni regolari (a quel punto, cercare r'\bis\b'
senza dividere è il modo più semplice e veloce per andare).
'is' not in (w.lower() for w in s.translate(string.maketrans(' ' * len(string.punctuation + string.whitespace), string.punctuation + string.whitespace)).split()
- ok, punto preso. Questo è ora ridicolo ...
Python ha una stringa che contiene il metodo di sottostringa?
Sì, ma Python ha un operatore di confronto che dovresti usare invece, perché la lingua ne prevede l'utilizzo e altri programmatori si aspettano che tu lo usi. Quella parola chiave è in
, che viene utilizzata come operatore di confronto:
>>> 'foo' in '**foo**'
True
Il contrario (complemento), che la domanda originale chiede, è not in
:
>>> 'foo' not in '**foo**' # returns False
False
Questo è semanticamente lo stesso not 'foo' in '**foo**'
ma è molto più leggibile ed esplicitamente previsto nella lingua come miglioramento della leggibilità.
__contains__
, find
eindex
Come promesso, ecco il contains
metodo:
str.__contains__('**foo**', 'foo')
ritorna True
. Puoi anche chiamare questa funzione dall'istanza della superstring:
'**foo**'.__contains__('foo')
Ma non farlo. I metodi che iniziano con i trattini bassi sono considerati semanticamente privati. L'unico motivo per utilizzare questo è quando si estende la funzionalità in
e not in
(ad esempio se la sottoclasse 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')
e adesso:
>>> 'substring' in ns
testing if "substring" in "a string with a substring inside"
True
Inoltre, evitare i seguenti metodi di stringa:
>>> '**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
Altre lingue potrebbero non avere metodi per testare direttamente le sottostringhe, quindi dovresti usare questi tipi di metodi, ma con Python è molto più efficiente usare l' in
operatore di confronto.
Possiamo confrontare vari modi per raggiungere lo stesso obiettivo.
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'))),
}
E ora vediamo che l'utilizzo in
è molto più veloce degli altri. Meno tempo per eseguire un'operazione equivalente è meglio:
>>> 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
e str.find
? In quale altro modo suggeriresti che qualcuno trovi l'indice di una sottostringa anziché solo se esiste o no? (o intendevi evitare di usarli al posto di contiene - quindi non usare s.find(ss) != -1
invece di ss in s
?)
re
modulo. Non ho ancora trovato un uso per str.index o str.find me stesso in qualsiasi codice che ho ancora scritto.
str.count
anche ( string.count(something) != 0
). brivido
operator
versione del modulo ?
in_
sopra - ma con uno stackframe attorno, quindi è più lento di così: github.com/python/cpython/blob/3.7/Lib/operator.py#L153
if needle in haystack:
è l'uso normale, come dice @Michael - si basa sull'operatore in
, più leggibile e più veloce di una chiamata di metodo.
Se avessi davvero bisogno di un metodo anziché di un operatore (ad esempio fare qualcosa di strano key=
per un tipo molto particolare ...?), Sarebbe 'haystack'.__contains__
. Ma dal momento che il tuo esempio è da usare in un if
, suppongo che non intendi davvero quello che dici ;-). Non è una buona forma (né leggibile, né efficiente) utilizzare direttamente metodi speciali - sono pensati per essere usati, invece, attraverso gli operatori e i builtin che li delegano.
in
Stringhe ed elenchi di PythonEcco alcuni esempi utili che parlano da soli riguardo al in
metodo:
"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]
Avvertimento. Gli elenchi sono iterabili e il in
metodo agisce sugli iterabili, non solo sulle stringhe.
["bar", "foo", "foobar"] in "foof"
:?
Se sei soddisfatto "blah" in somestring
ma vuoi che sia una chiamata funzione / metodo, probabilmente puoi farlo
import operator
if not operator.contains(somestring, "blah"):
continue
Tutti gli operatori in Python possono essere trovati più o meno nel modulo operatore incluso in
.
Quindi apparentemente non c'è nulla di simile per il confronto vettoriale. Un ovvio modo Python per farlo sarebbe:
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
non dovrebbe essere usato con le liste perché fa una scansione lineare degli elementi ed è lento rispetto. Utilizzare invece un set, soprattutto se i test di appartenenza devono essere eseguiti ripetutamente.
È possibile utilizzare y.count()
.
Restituirà il valore intero del numero di volte in cui una stringa secondaria appare in una stringa.
Per esempio:
string.count("bah") >> 0
string.count("Hello") >> 1
Ecco la tua risposta:
if "insert_char_or_string_here" in "insert_string_to_search_here":
#DOSTUFF
Per verificare se è falso:
if not "insert_char_or_string_here" in "insert_string_to_search_here":
#DOSTUFF
O:
if "insert_char_or_string_here" not in "insert_string_to_search_here":
#DOSTUFF
__contains__(self, item)
,__iter__(self)
e__getitem__(self, key)
in quell'ordine per determinare se un oggetto si trova in un dato contenitore. Implementa almeno uno di questi metodi per renderloin
disponibile per il tuo tipo personalizzato.