Unter der Haube wird Python verwenden __contains__(self, item), __iter__(self)und __getitem__(self, key)in dieser Reihenfolge , ob ein Element liegt enthält in einem bestimmten zu bestimmen. Implementieren Sie mindestens eine dieser Methoden, um insie Ihrem benutzerdefinierten Typ zur Verfügung zu stellen.
BallpointBen
27
Stellen Sie nur sicher, dass Somestring nicht None ist. Andernfalls erhalten Sie einenTypeError: argument of type 'NoneType' is not iterable
Big Pumpkin
5
FWIW, dies ist der idiomatische Weg, um dieses Ziel zu erreichen.
Trenton
6
inVerwendet der Python- Operator für Zeichenfolgen den Rabin-Carp-Algorithmus?
Sam Chats
3
@SamChats siehe stackoverflow.com/questions/18139660/… für die Implementierungsdetails (in CPython; afaik schreibt die Sprachspezifikation hier keinen bestimmten Algorithmus vor).
Christoph Burschka
667
Wenn es sich nur um eine Teilstringsuche handelt, können Sie diese verwenden string.find("substring").
Sie haben mit ein wenig vorsichtig sein find, indexund inwenn es , wie sie Suchen werden String. Mit anderen Worten:
s ="This be a string"if s.find("is")==-1:print("No 'is' here!")else:print("Found 'is' in the string.")
Es würde Found 'is' in the string.ähnlich drucken , if "is" in s:würde auswerten True. Dies kann sein oder nicht, was Sie wollen.
+1 zum Hervorheben der Fallstricke bei der Suche nach Teilzeichenfolgen. Die offensichtliche Lösung ist, if ' is ' in s:welche Falsewie (wahrscheinlich) erwartet zurückkehren wird.
Aaronasterling
95
@aaronasterling Offensichtlich mag es sein, aber nicht ganz richtig. Was ist, wenn Sie Interpunktion haben oder am Anfang oder Ende? Was ist mit Kapitalisierung? Besser wäre eine Suche ohne Berücksichtigung von Groß- und Kleinschreibung \bis\b(Wortgrenzen).
Bob
2
@JamieBull Noch einmal, Sie müssen überlegen, ob Sie Interpunktion als Trennzeichen für ein Wort einfügen möchten. Das Aufteilen hätte weitgehend den gleichen Effekt wie die naive Lösung der Überprüfung ' is ', insbesondere, ob es nicht fängt This is, a comma'oder nicht 'It is.'.
Bob
7
@JamieBull: Ich bezweifle sehr, dass sich eine echte Eingabeaufteilung s.split(string.punctuation + string.whitespace)auch nur einmal aufteilen würde. splitist nicht wie die strip/ rstrip/ lstripFunktionsfamilie, sondern wird nur aufgeteilt, wenn alle Trennzeichen zusammenhängend in genau dieser Reihenfolge angezeigt werden. Wenn Sie nach Zeichenklassen aufteilen möchten, kehren Sie zu regulären Ausdrücken zurück (an diesem Punkt ist das Suchen r'\bis\b'ohne Aufteilen der einfachere und schnellere Weg).
ShadowRanger
8
'is' not in (w.lower() for w in s.translate(string.maketrans(' ' * len(string.punctuation + string.whitespace), string.punctuation + string.whitespace)).split()- Ok, Punkt genommen. Das ist jetzt lächerlich ...
Jamie Bull
190
Hat Python eine Zeichenfolge, die eine Teilzeichenfolgenmethode enthält?
Ja, aber Python verfügt über einen Vergleichsoperator, den Sie stattdessen verwenden sollten, da die Sprache ihre Verwendung beabsichtigt und andere Programmierer von Ihnen erwarten, dass Sie ihn verwenden. Das Schlüsselwort lautet in, das als Vergleichsoperator verwendet wird:
>>>'foo'in'**foo**'True
Das Gegenteil (Ergänzung), nach dem die ursprüngliche Frage fragt, ist not in:
>>>'foo'notin'**foo**'# returns FalseFalse
Dies ist semantisch dasselbe wie, not 'foo' in '**foo**'aber es ist viel besser lesbar und in der Sprache explizit als Verbesserung der Lesbarkeit vorgesehen.
Vermeiden Sie __contains__, findundindex
Wie versprochen, hier ist die containsMethode:
str.__contains__('**foo**','foo')
kehrt zurück True. Sie können diese Funktion auch von der Instanz des Superstrings aus aufrufen:
'**foo**'.__contains__('foo')
Aber nicht. Methoden, die mit Unterstrichen beginnen, werden als semantisch privat betrachtet. Der einzige Grund, dies zu verwenden, ist die Erweiterung der inund not in-Funktionalität (z. B. bei Unterklassen 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')
und nun:
>>>'substring'in ns
testing if"substring"in"a string with a substring inside"True
Vermeiden Sie außerdem die folgenden Zeichenfolgenmethoden:
>>>'**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
In anderen Sprachen gibt es möglicherweise keine Methoden zum direkten Testen auf Teilzeichenfolgen. Daher müssten Sie diese Arten von Methoden verwenden. Mit Python ist es jedoch wesentlich effizienter, den inVergleichsoperator zu verwenden .
Leistungsvergleiche
Wir können verschiedene Wege vergleichen, um dasselbe Ziel zu erreichen.
Warum sollte man vermeiden str.indexund str.find? Wie sonst würden Sie vorschlagen, dass jemand den Index eines Teilstrings findet, anstatt nur, ob er existiert oder nicht? (oder s.find(ss) != -1ss in s
meintest
3
Genau so, obwohl die Absicht hinter der Verwendung dieser Methoden durch die elegante Verwendung des reModuls besser angegangen werden kann . Ich habe noch keine Verwendung für str.index gefunden oder finde mich in einem Code, den ich noch geschrieben habe.
Aaron Hall
Bitte erweitern Sie Ihre Antwort auf Ratschläge gegen die Verwendung str.countvon ( string.count(something) != 0). Schauder
if needle in haystack:ist die normale Verwendung, wie @Michael sagt - sie basiert auf dem inOperator, ist lesbarer und schneller als ein Methodenaufruf.
Wenn Sie wirklich eine Methode anstelle eines Operators benötigen (z. B. um etwas Seltsames key=für eine sehr eigenartige Art zu tun ...?), Wäre dies der Fall 'haystack'.__contains__. Aber da dein Beispiel für die Verwendung in einem ist if, meinst du wohl nicht wirklich, was du sagst ;-). Es ist keine gute Form (weder lesbar noch effizient), spezielle Methoden direkt zu verwenden - sie sollen stattdessen über die Operatoren und integrierten Funktionen verwendet werden, die an sie delegieren.
Hier einige nützliche Beispiele, die für die inMethode sprechen :
"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]
Vorbehalt. Listen sind iterable und die inMethode wirkt auf iterables, nicht nur auf Strings.
Könnte die iterierbare Liste umgeschaltet werden, um nach einer der Listen in einer einzelnen Zeichenfolge zu suchen? Bsp. : ["bar", "foo", "foobar"] in "foof"?
CaffeinatedCoder
1
@CaffeinatedCoder, nein, dies erfordert eine verschachtelte Iteration. „|“ .Join ([ „bar“, „foo“, „foobar“]) und die Erstellung einer Regex aus ihm heraus, dann passend auf „foof“ am besten durch Verbinden der Liste mit Rohren getan
firelynx
2
any ([x in "foof" für x in ["bar", "foo", "foobar"]])
Izaak Weiss
1
@IzaakWeiss Ihr One Liner funktioniert, ist aber nicht sehr lesbar und führt eine verschachtelte Iteration durch. Ich würde davon
abraten
1
@ PiyushS.Wanare was meinst du mit Komplexität? Die "WTF / min" ist bei Regex viel höher.
Firelynx
42
Wenn Sie zufrieden sind, "blah" in somestringaber möchten, dass es sich um einen Funktions- / Methodenaufruf handelt, können Sie dies wahrscheinlich tun
Das liegt daran, dass es unzählige Möglichkeiten gibt, ein Produkt aus atomaren Variablen zu erstellen. Sie können sie in ein Tupel, eine Liste (die Formen kartesischer Produkte sind und eine implizite Reihenfolge enthalten) einfügen, oder sie können als Eigenschaften einer Klasse (keine Reihenfolge von vornherein) oder als Wörterbuchwerte oder als Dateien in Dateien bezeichnet werden ein Verzeichnis oder was auch immer. Wann immer Sie etwas in einem 'Container' oder 'Kontext' eindeutig identifizieren (iterieren oder abrufen) können, können Sie diesen 'Container' als eine Art Vektor sehen und binäre Operationen darauf definieren. en.wikipedia.org/wiki/…
Niriel
Es ist nichts wert, was innicht mit Listen verwendet werden sollte, da es einen linearen Scan der Elemente durchführt und im Vergleich langsam ist. Verwenden Sie stattdessen einen Satz, insbesondere wenn Mitgliedschaftstests wiederholt durchgeführt werden sollen.
CS95
22
Sie können verwenden y.count().
Es wird der ganzzahlige Wert zurückgegeben, wie oft eine Unterzeichenfolge in einer Zeichenfolge angezeigt wird.
Das Zählen einer Zeichenfolge ist kostspielig, wenn Sie nur überprüfen möchten, ob sie vorhanden ist ...
Jean-François Fabre
3
Methoden, die im ursprünglichen Beitrag von 2010 vorhanden waren, so dass ich sie mit Konsens der Community herausgearbeitet habe (siehe Meta-Beitrag meta.stackoverflow.com/questions/385063/… )
Jean-François Fabre
17
Nein. Mein Punkt ist "warum genau das gleiche beantworten wie andere vor 9 Jahren"?
Wenn Sie die Berechtigung haben, es zu entfernen, entfernen Sie es. Andernfalls tun Sie, was Sie müssen, und fahren Sie fort. IMO diese Antwort Mehrwert, der sich in Up-Votes von Benutzern widerspiegelt.
__contains__(self, item)
,__iter__(self)
und__getitem__(self, key)
in dieser Reihenfolge , ob ein Element liegt enthält in einem bestimmten zu bestimmen. Implementieren Sie mindestens eine dieser Methoden, umin
sie Ihrem benutzerdefinierten Typ zur Verfügung zu stellen.TypeError: argument of type 'NoneType' is not iterable
in
Verwendet der Python- Operator für Zeichenfolgen den Rabin-Carp-Algorithmus?Wenn es sich nur um eine Teilstringsuche handelt, können Sie diese verwenden
string.find("substring")
.Sie haben mit ein wenig vorsichtig sein
find
,index
undin
wenn es , wie sie Suchen werden String. Mit anderen Worten:Es würde
Found 'is' in the string.
ähnlich drucken ,if "is" in s:
würde auswertenTrue
. Dies kann sein oder nicht, was Sie wollen.quelle
if ' is ' in s:
welcheFalse
wie (wahrscheinlich) erwartet zurückkehren wird.\bis\b
(Wortgrenzen).' is '
, insbesondere, ob es nicht fängtThis is, a comma'
oder nicht'It is.'
.s.split(string.punctuation + string.whitespace)
auch nur einmal aufteilen würde.split
ist nicht wie diestrip
/rstrip
/lstrip
Funktionsfamilie, sondern wird nur aufgeteilt, wenn alle Trennzeichen zusammenhängend in genau dieser Reihenfolge angezeigt werden. Wenn Sie nach Zeichenklassen aufteilen möchten, kehren Sie zu regulären Ausdrücken zurück (an diesem Punkt ist das Suchenr'\bis\b'
ohne Aufteilen der einfachere und schnellere Weg).'is' not in (w.lower() for w in s.translate(string.maketrans(' ' * len(string.punctuation + string.whitespace), string.punctuation + string.whitespace)).split()
- Ok, Punkt genommen. Das ist jetzt lächerlich ...Ja, aber Python verfügt über einen Vergleichsoperator, den Sie stattdessen verwenden sollten, da die Sprache ihre Verwendung beabsichtigt und andere Programmierer von Ihnen erwarten, dass Sie ihn verwenden. Das Schlüsselwort lautet
in
, das als Vergleichsoperator verwendet wird:Das Gegenteil (Ergänzung), nach dem die ursprüngliche Frage fragt, ist
not in
:Dies ist semantisch dasselbe wie,
not 'foo' in '**foo**'
aber es ist viel besser lesbar und in der Sprache explizit als Verbesserung der Lesbarkeit vorgesehen.Vermeiden Sie
__contains__
,find
undindex
Wie versprochen, hier ist die
contains
Methode:kehrt zurück
True
. Sie können diese Funktion auch von der Instanz des Superstrings aus aufrufen:Aber nicht. Methoden, die mit Unterstrichen beginnen, werden als semantisch privat betrachtet. Der einzige Grund, dies zu verwenden, ist die Erweiterung der
in
undnot in
-Funktionalität (z. B. bei Unterklassenstr
):und nun:
Vermeiden Sie außerdem die folgenden Zeichenfolgenmethoden:
In anderen Sprachen gibt es möglicherweise keine Methoden zum direkten Testen auf Teilzeichenfolgen. Daher müssten Sie diese Arten von Methoden verwenden. Mit Python ist es jedoch wesentlich effizienter, den
in
Vergleichsoperator zu verwenden .Leistungsvergleiche
Wir können verschiedene Wege vergleichen, um dasselbe Ziel zu erreichen.
Und jetzt sehen wir, dass die Verwendung
in
viel schneller ist als die anderen. Weniger Zeit für eine gleichwertige Operation ist besser:quelle
str.index
undstr.find
? Wie sonst würden Sie vorschlagen, dass jemand den Index eines Teilstrings findet, anstatt nur, ob er existiert oder nicht? (oders.find(ss) != -1
ss in s
re
Moduls besser angegangen werden kann . Ich habe noch keine Verwendung für str.index gefunden oder finde mich in einem Code, den ich noch geschrieben habe.str.count
von (string.count(something) != 0
). Schauderoperator
Modulversion ?in_
oben - aber mit einem Stackframe um es herum, also ist es langsamer als das: github.com/python/cpython/blob/3.7/Lib/operator.py#L153if needle in haystack:
ist die normale Verwendung, wie @Michael sagt - sie basiert auf demin
Operator, ist lesbarer und schneller als ein Methodenaufruf.Wenn Sie wirklich eine Methode anstelle eines Operators benötigen (z. B. um etwas Seltsames
key=
für eine sehr eigenartige Art zu tun ...?), Wäre dies der Fall'haystack'.__contains__
. Aber da dein Beispiel für die Verwendung in einem istif
, meinst du wohl nicht wirklich, was du sagst ;-). Es ist keine gute Form (weder lesbar noch effizient), spezielle Methoden direkt zu verwenden - sie sollen stattdessen über die Operatoren und integrierten Funktionen verwendet werden, die an sie delegieren.quelle
in
Python-Zeichenfolgen und -ListenHier einige nützliche Beispiele, die für die
in
Methode sprechen :Vorbehalt. Listen sind iterable und die
in
Methode wirkt auf iterables, nicht nur auf Strings.quelle
["bar", "foo", "foobar"] in "foof"
?Wenn Sie zufrieden sind,
"blah" in somestring
aber möchten, dass es sich um einen Funktions- / Methodenaufruf handelt, können Sie dies wahrscheinlich tunAlle Operatoren in Python befinden sich mehr oder weniger im Operatormodul einschließlich
in
.quelle
Anscheinend gibt es nichts Vergleichbares für den vektorweisen Vergleich. Ein naheliegender Python-Weg wäre:
quelle
in
nicht mit Listen verwendet werden sollte, da es einen linearen Scan der Elemente durchführt und im Vergleich langsam ist. Verwenden Sie stattdessen einen Satz, insbesondere wenn Mitgliedschaftstests wiederholt durchgeführt werden sollen.Sie können verwenden
y.count()
.Es wird der ganzzahlige Wert zurückgegeben, wie oft eine Unterzeichenfolge in einer Zeichenfolge angezeigt wird.
Zum Beispiel:
quelle
Hier ist deine Antwort:
Um zu überprüfen, ob es falsch ist:
ODER:
quelle
Sie können reguläre Ausdrücke verwenden, um die Vorkommen abzurufen:
quelle