Sob o capô, o Python usará __contains__(self, item), __iter__(self)e __getitem__(self, key)nessa ordem para determinar se um item está em um determinado conteúdo. Implemente pelo menos um desses métodos para indisponibilizar seu tipo personalizado.
usar o seguinte
27
Apenas certifique-se de que somestring não será None. Caso contrário, você terá umTypeError: argument of type 'NoneType' is not iterable
Big Pumpkin
5
FWIW, esta é a maneira idiomática de alcançar esse objetivo.
Trenton
6
Para strings, o inoperador Python usa o algoritmo Rabin-Carp?
Sam Chats
3
@SamChats consulte stackoverflow.com/questions/18139660/… para obter os detalhes da implementação (no CPython; depois que a especificação da linguagem não exige nenhum algoritmo específico aqui).
Christoph Burschka
667
Se for apenas uma pesquisa de substring, você pode usar string.find("substring").
Você tem que ser um pouco cuidadoso com find, indexe, inno entanto, como eles são substring pesquisas. Em outras palavras, isso:
s ="This be a string"if s.find("is")==-1:print("No 'is' here!")else:print("Found 'is' in the string.")
Seria imprimir Found 'is' in the string.Da mesma forma, if "is" in s:avaliaria para True. Isso pode ou não ser o que você deseja.
+1 para destacar as dicas envolvidas nas pesquisas de substring. a solução óbvia é a if ' is ' in s:que retornará Falsecomo é (provavelmente) esperado.
precisa saber é o seguinte
95
@aaronasterling Óbvio que pode ser, mas não totalmente correto. E se você tiver pontuação ou no início ou no final? E a capitalização? Melhor seria uma pesquisa de regex que não diferencia maiúsculas de minúsculas \bis\b(limites de palavras).
Bob
2
@JamieBull Mais uma vez, você deve considerar se deseja incluir pontuação como delimitador de uma palavra. A divisão teria em grande parte o mesmo efeito que a solução ingênua de verificar ' is ', notavelmente, ela não pegará This is, a comma'ou 'It is.'.
Bob
7
@JamieBull: Eu duvido que qualquer divisão real de entrada s.split(string.punctuation + string.whitespace)seja dividida uma vez; splitnão é como a família strip/ rstrip/ lstripde funções, apenas se divide quando vê todos os caracteres delimitadores, contiguamente, nessa ordem exata. Se você deseja dividir as classes de caracteres, volta às expressões regulares (nesse ponto, procurar r'\bis\b'sem dividir é o caminho mais simples e rápido).
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, ponto de vista. Isto agora é ridículo ...
Jamie Touro
190
O Python possui uma string que contém o método de substring?
Sim, mas o Python possui um operador de comparação que você deve usar, porque a linguagem pretende seu uso, e outros programadores esperam que você o use. Essa palavra-chave é inusada como um operador de comparação:
>>>'foo'in'**foo**'True
O oposto (complemento), que a pergunta original pede, é not in:
>>>'foo'notin'**foo**'# returns FalseFalse
É semanticamente o mesmo, not 'foo' in '**foo**'mas é muito mais legível e explicitamente previsto no idioma como uma melhoria de legibilidade.
Evitar o uso __contains__, findeindex
Como prometido, aqui está o containsmétodo:
str.__contains__('**foo**','foo')
retorna True. Você também pode chamar esta função a partir da instância da supercorda:
'**foo**'.__contains__('foo')
Mas não. Os métodos que começam com sublinhados são considerados semanticamente privados. A única razão para usar isso é ao estender a funcionalidade ine not in(por exemplo, se estiver subclassificando 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')
e agora:
>>>'substring'in ns
testing if"substring"in"a string with a substring inside"True
Além disso, evite os seguintes métodos de string:
>>>'**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
Outras linguagens podem não ter métodos para testar diretamente substrings e, portanto, você teria que usar esses tipos de métodos, mas com o Python, é muito mais eficiente usar o inoperador de comparação.
Comparações de desempenho
Podemos comparar várias maneiras de alcançar o mesmo objetivo.
Por que alguém deveria evitar str.indexe str.find? De que outra forma você sugeriria que alguém encontrasse o índice de uma substring em vez de apenas existir ou não? (ou você evitar média de usá-los no lugar de contém - portanto, não use s.find(ss) != -1em vez de ss in s?)
coderforlife
3
Precisamente, embora a intenção por trás do uso desses métodos possa ser melhor abordada pelo uso elegante do remódulo. Ainda não encontrei um uso para str.index ou str.find em qualquer código que eu escrevi ainda.
Aaron Hall
Por favor, estenda sua resposta ao conselho contra o uso str.counttambém ( string.count(something) != 0). shudder
if needle in haystack:é o uso normal, como o @Michael diz - depende do inoperador, mais legível e mais rápido que uma chamada de método.
Se você realmente precisa de um método em vez de um operador (por exemplo, fazer algo estranho key=para um tipo muito peculiar ...?), Isso seria 'haystack'.__contains__. Mas como seu exemplo é para uso em um if, acho que você não está realmente falando sério ;-). Não é uma boa forma (nem legível, nem eficiente) usar métodos especiais diretamente - eles devem ser usados, em vez disso, através dos operadores e componentes internos que os delegam.
Aqui estão alguns exemplos úteis que falam por si sobre o inmétodo:
"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]
Embargo. Listas são iteráveis, e o inmétodo atua em iterables, não apenas em strings.
A lista iterável poderia ser alternada para procurar qualquer lista em uma única sequência? Ex ["bar", "foo", "foobar"] in "foof":?
precisa
1
@CaffeinatedCoder, não, isso requer iteração aninhada. Melhor feito juntando-se a lista com tubulações "|" .join ([ "bar", "foo", "foobar"]) e compilar um regex fora dele, em seguida, combinando em "foof"
firelynx
2
any ([x em "foof" para x em ["bar", "foo", "foobar"]])
Izaak Weiss
1
@IzaakWeiss Seu liner único funciona, mas não é muito legível e faz iteração aninhada. Eu aconselho a não fazer isso
firelynx
1
@ PiyushS.Wanare o que você quer dizer com complexidade? O "WTF / min" é muito maior com o regex.
firelynx
42
Se você está satisfeito, "blah" in somestringmas deseja que seja uma chamada de função / método, provavelmente poderá fazer isso
Isso ocorre porque existem inúmeras maneiras de criar um Produto a partir de variáveis atômicas. Você pode colocá-los em uma tupla, em uma lista (que são formas de produtos cartesianos e vêm com uma ordem implícita) ou podem ser nomeadas propriedades de uma classe (sem ordem a priori) ou valores de dicionário, ou podem ser arquivos em um diretório ou qualquer outra coisa. Sempre que você puder identificar (iter ou getitem) algo em um 'contêiner' ou 'contexto', poderá vê-lo como um tipo de vetor e definir operações binárias nele. pt.wikipedia.org/wiki/…
Niriel 10/08/15
Vale nada que innão deva ser usado com listas porque faz uma varredura linear dos elementos e é lento em comparação. Use um conjunto, especialmente se os testes de associação forem feitos repetidamente.
precisa saber é
22
Você pode usar y.count().
Ele retornará o valor inteiro do número de vezes que uma sub string aparecerá em uma string.
contar uma string é caro quando você só quer verificar se existe ...
Jean-François Fabre
3
métodos que existem na postagem original de 2010, então acabei editando-os, com consenso da comunidade (consulte meta post meta.stackoverflow.com/questions/385063/… )
Jean-François Fabre
17
não. Meu argumento é "por que responder exatamente a mesma coisa que os outros fizeram 9 anos atrás"?
Se você tiver autoridade para removê-lo, remova-o; faça o que for necessário e siga em frente. Na IMO, esta resposta agrega valor, refletido por votos positivos dos usuários.
__contains__(self, item)
,__iter__(self)
e__getitem__(self, key)
nessa ordem para determinar se um item está em um determinado conteúdo. Implemente pelo menos um desses métodos parain
disponibilizar seu tipo personalizado.TypeError: argument of type 'NoneType' is not iterable
in
operador Python usa o algoritmo Rabin-Carp?Se for apenas uma pesquisa de substring, você pode usar
string.find("substring")
.Você tem que ser um pouco cuidadoso com
find
,index
e,in
no entanto, como eles são substring pesquisas. Em outras palavras, isso:Seria imprimir
Found 'is' in the string.
Da mesma forma,if "is" in s:
avaliaria paraTrue
. Isso pode ou não ser o que você deseja.fonte
if ' is ' in s:
que retornaráFalse
como é (provavelmente) esperado.\bis\b
(limites de palavras).' is '
, notavelmente, ela não pegaráThis is, a comma'
ou'It is.'
.s.split(string.punctuation + string.whitespace)
seja dividida uma vez;split
não é como a famíliastrip
/rstrip
/lstrip
de funções, apenas se divide quando vê todos os caracteres delimitadores, contiguamente, nessa ordem exata. Se você deseja dividir as classes de caracteres, volta às expressões regulares (nesse ponto, procurarr'\bis\b'
sem dividir é o caminho mais simples e rápido).'is' not in (w.lower() for w in s.translate(string.maketrans(' ' * len(string.punctuation + string.whitespace), string.punctuation + string.whitespace)).split()
- ok, ponto de vista. Isto agora é ridículo ...Sim, mas o Python possui um operador de comparação que você deve usar, porque a linguagem pretende seu uso, e outros programadores esperam que você o use. Essa palavra-chave é
in
usada como um operador de comparação:O oposto (complemento), que a pergunta original pede, é
not in
:É semanticamente o mesmo,
not 'foo' in '**foo**'
mas é muito mais legível e explicitamente previsto no idioma como uma melhoria de legibilidade.Evitar o uso
__contains__
,find
eindex
Como prometido, aqui está o
contains
método:retorna
True
. Você também pode chamar esta função a partir da instância da supercorda:Mas não. Os métodos que começam com sublinhados são considerados semanticamente privados. A única razão para usar isso é ao estender a funcionalidade
in
enot in
(por exemplo, se estiver subclassificandostr
):e agora:
Além disso, evite os seguintes métodos de string:
Outras linguagens podem não ter métodos para testar diretamente substrings e, portanto, você teria que usar esses tipos de métodos, mas com o Python, é muito mais eficiente usar o
in
operador de comparação.Comparações de desempenho
Podemos comparar várias maneiras de alcançar o mesmo objetivo.
E agora vemos que o uso
in
é muito mais rápido que os outros. Menos tempo para realizar uma operação equivalente é melhor:fonte
str.index
estr.find
? De que outra forma você sugeriria que alguém encontrasse o índice de uma substring em vez de apenas existir ou não? (ou você evitar média de usá-los no lugar de contém - portanto, não uses.find(ss) != -1
em vez dess in s
?)re
módulo. Ainda não encontrei um uso para str.index ou str.find em qualquer código que eu escrevi ainda.str.count
também (string.count(something) != 0
). shudderoperator
versão do módulo ?in_
acima - mas com um StackFrame em torno dele, por isso é mais lento do que isso: github.com/python/cpython/blob/3.7/Lib/operator.py#L153if needle in haystack:
é o uso normal, como o @Michael diz - depende doin
operador, mais legível e mais rápido que uma chamada de método.Se você realmente precisa de um método em vez de um operador (por exemplo, fazer algo estranho
key=
para um tipo muito peculiar ...?), Isso seria'haystack'.__contains__
. Mas como seu exemplo é para uso em umif
, acho que você não está realmente falando sério ;-). Não é uma boa forma (nem legível, nem eficiente) usar métodos especiais diretamente - eles devem ser usados, em vez disso, através dos operadores e componentes internos que os delegam.fonte
in
Strings e listas PythonAqui estão alguns exemplos úteis que falam por si sobre o
in
método:Embargo. Listas são iteráveis, e o
in
método atua em iterables, não apenas em strings.fonte
["bar", "foo", "foobar"] in "foof"
:?Se você está satisfeito,
"blah" in somestring
mas deseja que seja uma chamada de função / método, provavelmente poderá fazer issoTodos os operadores no Python podem ser mais ou menos encontrados no módulo do operador inclusive
in
.fonte
Então, aparentemente, não há nada semelhante para a comparação vetorial. Uma maneira óbvia de Python para fazer isso seria:
fonte
in
não deva ser usado com listas porque faz uma varredura linear dos elementos e é lento em comparação. Use um conjunto, especialmente se os testes de associação forem feitos repetidamente.Você pode usar
y.count()
.Ele retornará o valor inteiro do número de vezes que uma sub string aparecerá em uma string.
Por exemplo:
fonte
Aqui está a sua resposta:
Para verificar se é falso:
OU:
fonte
Você pode usar expressões regulares para obter as ocorrências:
fonte