파이썬에는 문자열 'contains'하위 문자열 방법이 있습니까?


3599

파이썬에서 string.contains또는 string.indexof메소드를 찾고 있습니다.

나하고 싶어:

if not somestring.contains("blah"):
   continue

답변:


6257

in연산자 를 사용할 수 있습니다 .

if "blah" not in somestring: 
    continue

230
후드, 파이썬은 사용 __contains__(self, item), __iter__(self)__getitem__(self, key)특정의 항목 거짓말이 포함되어 있는지 여부를 결정하는 순서입니다. in사용자 정의 유형에 사용할 수 있도록 이러한 방법 중 하나 이상을 구현 하십시오.
BallpointBen

27
somestring이 None이 아닌지 확인하십시오. 그렇지 않으면TypeError: argument of type 'NoneType' is not iterable
Big Pumpkin

5
FWIW,이 목표를 달성하는 관용적 방법입니다.
Trenton

6
문자열의 경우 Python in연산자는 Rabin-Carp 알고리즘을 사용합니까?
Sam Chats

3
@SamChats 는 구현 세부 사항에 대해서는 stackoverflow.com/questions/18139660/… 을 참조 하십시오 (CPython에서; 언어 사양은 여기에서 특정 알고리즘을 요구하지 않습니다).
Christoph Burschka

667

하위 문자열 검색 인 경우을 사용할 수 있습니다 string.find("substring").

하위 문자열 검색 find이므로 index,에 약간주의해야합니다 in. 다시 말해, 이것은 :

s = "This be a string"
if s.find("is") == -1:
    print("No 'is' here!")
else:
    print("Found 'is' in the string.")

Found 'is' in the string.비슷하게 인쇄 if "is" in s:됩니다 True. 이것은 당신이 원하는 것일 수도 아닐 수도 있습니다.


78
하위 문자열 검색과 관련된 문제를 강조 표시하기 위해 +1 확실한 해결책은 (아마도) 예상대로 if ' is ' in s:돌아올 False것입니다.
aaronasterling

94
@aaronasterling 분명하지만 완전히 정확하지는 않습니다. 문장 부호가 있거나 시작 또는 끝에있는 경우 어떻게합니까? 대문자는 어떻습니까? 대소 문자를 구분하지 않는 정규식 검색 \bis\b(단어 경계)이 더 좋습니다.
Bob

2
@JamieBull 다시 한 번 문장 부호를 단어의 구분 기호로 포함하려면 고려해야합니다. 스 플리 팅은 ' is '특히, This is, a comma'또는을 잡을 수없는 순진한 솔루션과 동일한 효과를냅니다 'It is.'.
Bob

7
@JamieBull : 실제 입력 분할은 s.split(string.punctuation + string.whitespace)한 번이라도 분할 될 것입니다. / / 계열 함수 split와 같지 않고 , 모든 구분 문자를 연속적인 순서로 연속적으로 볼 때만 분할됩니다. 문자 클래스를 분할하려면 정규 표현식으로 돌아갑니다 ( 분할하지 않고 검색하는 것이 더 간단하고 빠른 방법 임). striprstriplstripr'\bis\b'
ShadowRanger

8
'is' not in (w.lower() for w in s.translate(string.maketrans(' ' * len(string.punctuation + string.whitespace), string.punctuation + string.whitespace)).split()-알았어. 이것은 지금 말도 안됩니다 ...
Jamie Bull

190

파이썬에 문자열에 하위 문자열 방법이 있습니까?

그렇습니다.하지만 파이썬에는 언어를 사용하려고 의도하는 다른 연산자가 있습니다. 다른 프로그래머는 그 언어를 사용할 것으로 기대하기 때문입니다. 해당 키워드는 in비교 연산자로 사용됩니다.

>>> 'foo' in '**foo**'
True

원래 질문에서 요구하는 반대 (보완)는 not in다음과 같습니다.

>>> 'foo' not in '**foo**' # returns False
False

이것은 의미 적으로 동일 not 'foo' in '**foo**'하지만 가독성 향상으로 언어에서 훨씬 더 읽기 쉽고 명확하게 제공됩니다.

사용하지 마십시오 __contains__, find그리고index

약속 한대로 contains방법은 다음과 같습니다.

str.__contains__('**foo**', 'foo')

을 반환합니다 True. 수퍼 스트링 인스턴스에서이 함수를 호출 할 수도 있습니다.

'**foo**'.__contains__('foo')

그러나하지 마십시오. 밑줄로 시작하는 메소드는 의미 상 개인용으로 간주됩니다. 이것을 사용하는 유일한 이유는 inand not in기능을 확장 할 때입니다 (예 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')

그리고 지금:

>>> 'substring' in ns
testing if "substring" in "a string with a substring inside"
True

또한 다음 문자열 방법을 피하십시오.

>>> '**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

다른 언어에는 하위 문자열을 직접 테스트하는 메소드가 없을 수 있으므로 이러한 유형의 메소드를 사용해야하지만 Python에서는 in비교 연산자 를 사용하는 것이 훨씬 효율적 입니다.

성능 비교

동일한 목표를 달성하는 다양한 방법을 비교할 수 있습니다.

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'))),
}

그리고 이제 우리 in는 다른 것보다 사용 속도가 훨씬 빠릅니다. 동등한 작업을 수행하는 데 걸리는 시간이 짧을수록 좋습니다.

>>> 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}

6
왜 사람은 피해야 str.index하고 str.find? 하위 문자열의 존재 여부와 상관없이 하위 문자열의 색인을 찾도록 제안하는 다른 방법은 무엇입니까? (또는 포함 s.find(ss) != -1대신에 사용하지 않는 것을 의미 했 ss in s습니까? 대신에 사용하지 마십시오 .)
coderforlife

3
re모듈 을 우아하게 사용하면 이러한 방법을 사용하려는 의도가 더 잘 해결 될 수 있지만 정확하게 그렇게 할 수 있습니다 . 아직 작성한 코드에서 str.index 또는 str.find에 대한 사용을 아직 찾지 못했습니다.
Aaron Hall

사용에 대한 조언으로 답변을 확장하십시오 str.count( string.count(something) != 0). 떨림
cs95

operator모듈 버전 은 어떻게 작동 합니까?
jpmc26

@ jpmc26 in_위와 동일 하지만 주위에 스택 프레임이 있으므로 그보다
Aaron Hall

175

if needle in haystack:@Michael이 말한 것처럼 일반적인 사용법입니다- in메소드 호출보다 더 읽기 쉽고 빠릅니다.

연산자 대신 메소드가 정말로 필요하다면 (예를 들어 key=매우 특이한 종류의 경우 이상한 것을 원한다면 ...?), 그럴 것입니다 'haystack'.__contains__. 그러나 귀하의 예는에서 사용하기 if때문에 실제로 당신이 말하는 것을 의미하지는 않습니다 ;-). 특수한 메소드를 직접 사용하는 것은 좋은 형태 (읽기 어렵거나 효율적이지 않음)가 아닙니다. 대신에 메소드를 위임하는 연산자와 내장을 통해 사용되어야합니다.


55

in 파이썬 문자열과리스트

다음은이 in방법과 관련하여 유용한 몇 가지 유용한 예입니다 .

"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]

경고. 리스트는 반복 가능하며, in메소드는 문자열뿐만 아니라 반복 가능에 작용합니다.


1
반복 가능한 목록을 전환하여 단일 문자열에서 목록을 찾을 수 있습니까? 예 : ["bar", "foo", "foobar"] in "foof"?
CaffeinatedCoder 2018 년

1
@CaffeinatedCoder, 아니요, 중첩 반복이 필요합니다. 파이프 "|".join ([ "bar", "foo", "foobar"])와 목록을 결합하고 정규식을 컴파일 한 다음 "foof"와 일치
시켜서

2
any ([[bar], "foo", "foobar"]의 x에 대한 "foof"의 x)]
Izaak Weiss

1
@IzaakWeiss 하나의 라이너가 작동하지만 읽을 수 없으며 중첩 된 반복을 수행합니다. 나는이 일에 대해 조언을 것입니다
firelynx

1
복잡성이란 무엇을 의미합니까? "WTF / min"은 정규식보다 훨씬 높습니다.
firelynx

42

당신이 만족 "blah" in somestring하지만 그것이 함수 / 메소드 호출이기를 원한다면, 아마도 이것을 할 수 있습니다.

import operator

if not operator.contains(somestring, "blah"):
    continue

파이썬의 모든 연산자는를 포함 하여 연산자 모듈 에서 다소 찾을 수 있습니다 in.


40

따라서 벡터와 비교하기에는 비슷한 것이 없습니다. 그렇게하는 명백한 파이썬 방법은 다음과 같습니다.

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

1
원자 변수에서 제품을 만드는 방법은 다양하기 때문입니다. 튜플, 목록 (카티 전 곱의 형태로 묵시적 순서와 함께 제공됨) 또는 클래스의 속성 (선험적 순서 없음) 또는 사전 값으로 이름을 지정할 수 있습니다. 디렉토리 또는 무엇이든. '컨테이너'또는 '컨텍스트'에서 무언가를 고유하게 식별 (iter 또는 getitem) 할 수있을 때마다 해당 '컨테이너'를 일종의 벡터로보고 이진 op를 정의 할 수 있습니다. en.wikipedia.org/wiki/…
Niriel

가치 아무것도 in는 요소의 선형 스캔을 수행하기 때문에 목록에 사용할 수 없습니다 느린 비교된다. 특히 멤버십 테스트를 반복적으로 수행해야하는 경우 대신 세트를 사용하십시오.
cs95

22

사용할 수 있습니다 y.count().

하위 문자열이 문자열에 나타나는 횟수의 정수 값을 반환합니다.

예를 들면 다음과 같습니다.

string.count("bah") >> 0
string.count("Hello") >> 1

8
현이 있는지 확인 하고 싶을 때 현을 세는 것은 비용이 많이 듭니다 ...
Jean-François Fabre

3
나는 사회의 합의와 함께, 그들을 편집 결국 있도록 2010 년부터 원래의 게시물에 존재하는 방법 (메타 포스트 참조 meta.stackoverflow.com/questions/385063/...를 )
장 - 프랑수아 파브르

17
아니. 내 요점은 "왜 다른 사람들이 9 년 전에했던 것과 똑같은 대답을 하는가?"입니다.
Jean-François Fabre

10
내가 사이트를 운영 할 거니까 ... 난 메타에 대한 질문을 요청했습니다 meta.stackoverflow.com/questions/385063/...을
장 - 프랑수아 파브르

2
그런 다음 제거 할 수있는 권한이 있으면 제거하십시오. 그렇지 않으면 필요한 사항을 수행하고 계속하십시오. IMO이 답변은 가치를 추가하며, 이는 사용자의 투표에 반영됩니다.
Brandon Bailey

20

답은 다음과 같습니다.

if "insert_char_or_string_here" in "insert_string_to_search_here":
    #DOSTUFF

그것이 거짓인지 확인하기 위해 :

if not "insert_char_or_string_here" in "insert_string_to_search_here":
    #DOSTUFF

또는:

if "insert_char_or_string_here" not in "insert_string_to_search_here":
    #DOSTUFF

8

정규식을 사용하여 어커런스를 얻을 수 있습니다.

>>> import re
>>> print(re.findall(r'( |t)', to_search_in)) # searches for t or space
['t', ' ', 't', ' ', ' ']
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.