Ik ben op zoek naar een string.contains
of string.indexof
methode in Python.
Ik wil doen:
if not somestring.contains("blah"):
continue
Antwoord 1, autoriteit 100%
Je kunt de in
operator:
if "blah" not in somestring:
continue
Antwoord 2, autoriteit 11%
Als het alleen om een substring-zoekopdracht gaat, kun je string.find("substring")
gebruiken.
Je moet wel een beetje voorzichtig zijn met find
, index
, en in
omdat ze zijn substring-zoekopdrachten. Met andere woorden, dit:
s = "This be a string"
if s.find("is") == -1:
print("No 'is' here!")
else:
print("Found 'is' in the string.")
Het zou Found 'is' in the string.
Op dezelfde manier zou if "is" in s:
resulteren in True
. Dit kan wel of niet zijn wat je wilt.
Antwoord 3, autoriteit 4%
Heeft Python een string bevat substring methode?
99% van de gebruiksgevallen wordt gedekt met het trefwoord in
, dat True
of False
oplevert :
'substring' in any_string
Voor het gebruik van de index, gebruik str.find
(die -1 retourneert bij mislukking en optionele positionele argumenten heeft):
start = 0
stop = len(any_string)
any_string.find('substring', start, stop)
of str.index
(zoals find
maar verhoogt ValueError bij mislukking):
start = 100
end = 1000
any_string.index('substring', start, end)
Uitleg
Gebruik de vergelijkingsoperator in
omdat
- de taal is bedoeld voor gebruik, en
- andere Python-programmeurs verwachten dat je het gebruikt.
>>> 'foo' in '**foo**'
True
Het tegenovergestelde (complement), waar de oorspronkelijke vraag om vroeg, is not in
:
>>> 'foo' not in '**foo**' # returns False
False
Dit is semantisch hetzelfde als not 'foo' in '**foo**'
maar het is veel leesbaarder en expliciet voorzien in de taal als een verbetering van de leesbaarheid.
Vermijd het gebruik van __contains__
De "bevat" methode implementeert het gedrag voor in
. Dit voorbeeld,
str.__contains__('**foo**', 'foo')
retourneert True
. Je zou deze functie ook kunnen aanroepen vanuit de instantie van de superstring:
'**foo**'.__contains__('foo')
Maar niet doen. Methoden die beginnen met onderstrepingstekens worden semantisch niet-openbaar beschouwd. De enige reden om dit te gebruiken is bij het implementeren of uitbreiden van de functionaliteiten in
en not in
(bijv. bij subclassificatie van str
):
class NoisyString(str):
def __contains__(self, other):
print(f'testing if "{other}" in "{self}"')
return super(NoisyString, self).__contains__(other)
ns = NoisyString('a string with a substring inside')
en nu:
>>> 'substring' in ns
testing if "substring" in "a string with a substring inside"
True
Gebruik find
en index
niet om te testen op "bevat"
Gebruik niet de volgende tekenreeksmethoden om te testen op "bevat":
>>> '**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
Andere talen hebben mogelijk geen methoden om rechtstreeks op substrings te testen, en daarom zou u dit soort methoden moeten gebruiken, maar met Python is het veel efficiënter om de vergelijkingsoperator in
te gebruiken.
Dit zijn ook geen vervangingen voor in
. Mogelijk moet u de uitzondering of -1
-gevallen afhandelen, en als ze 0
retourneren (omdat ze de substring aan het begin hebben gevonden), is de booleaanse interpretatie False
in plaats van True
.
Als je echt not any_string.startswith(substring)
bedoelt, zeg het dan.
Prestatievergelijkingen
We kunnen verschillende manieren vergelijken om hetzelfde doel te bereiken.
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'))),
}
En nu zien we dat het gebruik van in
veel sneller is dan de andere.
Minder tijd om een gelijkwaardige bewerking uit te voeren is beter:
>>> 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}
Hoe kan in
sneller zijn dan __contains__
als in
__contains__
gebruikt?
Dit is een prima vervolgvraag.
Laten we functies demonteren met de van belang zijnde methoden:
>>> from dis import dis
>>> dis(lambda: 'a' in 'b')
1 0 LOAD_CONST 1 ('a')
2 LOAD_CONST 2 ('b')
4 COMPARE_OP 6 (in)
6 RETURN_VALUE
>>> dis(lambda: 'b'.__contains__('a'))
1 0 LOAD_CONST 1 ('b')
2 LOAD_METHOD 0 (__contains__)
4 LOAD_CONST 2 ('a')
6 CALL_METHOD 1
8 RETURN_VALUE
we zien dus dat de methode .__contains__
apart moet worden opgezocht en vervolgens moet worden aangeroepen vanaf de virtuele Python-machine – dit zou het verschil voldoende moeten verklaren.
Antwoord 4, autoriteit 3%
if needle in haystack:
is het normale gebruik, zoals @Michael zegt — het vertrouwt op de in
operator, leesbaarder en sneller dan een methodeaanroep.
Als je echt een methode nodig hebt in plaats van een operator (bijvoorbeeld om een rare key=
te doen voor een heel eigenaardige soort…?), zou dat 'haystack'.__contains__
. Maar aangezien je voorbeeld bedoeld is voor gebruik in een if
, denk ik dat je niet echt meent wat je zegt;-). Het is geen goede vorm (noch leesbaar, noch efficiënt) om speciale methoden rechtstreeks te gebruiken — ze zijn bedoeld om in plaats daarvan te worden gebruikt via de operators en ingebouwde instellingen die aan hen delegeren.
Antwoord 5
in
Python-strings en lijsten
Hier zijn een paar bruikbare voorbeelden die voor zich spreken met betrekking tot de in
methode:
>>> "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]
Voorbehoud. Lijsten zijn herhalingen en de methode in
werkt op herhalingen, niet alleen op tekenreeksen.
Antwoord 6
Als u tevreden bent met "blah" in somestring
maar wilt dat het een functie/methode-aanroep is, kunt u dit waarschijnlijk doen
import operator
if not operator.contains(somestring, "blah"):
continue
Alle operators in Python zijn min of meer te vinden in de operatormodule inclusief in
.
Antwoord 7
Dus blijkbaar is er niets vergelijkbaars voor vectorgewijze vergelijking. Een voor de hand liggende Python-manier om dit te doen zou zijn:
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
Antwoord 8
U kunt y.count()
gebruiken.
Het retourneert de gehele waarde van het aantal keren dat een subtekenreeks in een tekenreeks voorkomt.
Bijvoorbeeld:
string.count("bah") >> 0
string.count("Hello") >> 1
Antwoord 9
Hier is uw antwoord:
if "insert_char_or_string_here" in "insert_string_to_search_here":
#DOSTUFF
Om te controleren of het onwaar is:
if not "insert_char_or_string_here" in "insert_string_to_search_here":
#DOSTUFF
OF:
if "insert_char_or_string_here" not in "insert_string_to_search_here":
#DOSTUFF
Antwoord 10
U kunt reguliere expressies gebruiken om de voorkomens te krijgen:
>>> import re
>>> print(re.findall(r'( |t)', to_search_in)) # searches for t or space
['t', ' ', 't', ' ', ' ']