Heeft Python een string ‘bevat’ substring-methode?

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

  1. de taal is bedoeld voor gebruik, en
  2. 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', ' ', ' ']

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Other episodes