Réponses:
Vous pouvez utiliser l' in
opérateur :
if "blah" not in somestring:
continue
TypeError: argument of type 'NoneType' is not iterable
in
opérateur Python utilise-t-il l'algorithme Rabin-Carp?
Si c'est juste une recherche de sous-chaîne que vous pouvez utiliser string.find("substring")
.
Vous ne devez être un peu prudent avec find
, index
et in
si, comme ils sont sousChaîne recherches. En d'autres termes, ceci:
s = "This be a string"
if s.find("is") == -1:
print("No 'is' here!")
else:
print("Found 'is' in the string.")
Il imprimerait de la Found 'is' in the string.
même manière, if "is" in s:
évaluerait True
. Cela peut ou non être ce que vous voulez.
if ' is ' in s:
qui reviendra False
comme prévu (probablement).
\bis\b
(limites de mots).
' is '
, notamment, il n'attrapera pas This is, a comma'
ou 'It is.'
.
s.split(string.punctuation + string.whitespace)
se divise même une fois; split
n'est pas comme la famille de fonctions strip
/ rstrip
/ lstrip
, elle ne se divise que lorsqu'elle voit tous les caractères délimiteurs, contigus, dans cet ordre exact. Si vous souhaitez diviser les classes de caractères, vous revenez aux expressions régulières (à quel moment, rechercher r'\bis\b'
sans fractionner est le moyen le plus simple et le plus rapide).
'is' not in (w.lower() for w in s.translate(string.maketrans(' ' * len(string.punctuation + string.whitespace), string.punctuation + string.whitespace)).split()
- ok, remarque prise. C'est maintenant ridicule ...
Python a-t-il une chaîne contenant une méthode de sous-chaîne?
Oui, mais Python a un opérateur de comparaison que vous devez utiliser à la place, car le langage a l'intention de l'utiliser, et d'autres programmeurs s'attendront à ce que vous l'utilisiez. Ce mot-clé est in
utilisé comme opérateur de comparaison:
>>> 'foo' in '**foo**'
True
Le contraire (complément), que la question initiale demande, est not in
:
>>> 'foo' not in '**foo**' # returns False
False
C'est sémantiquement le même que not 'foo' in '**foo**'
mais c'est beaucoup plus lisible et explicitement prévu dans le langage comme une amélioration de la lisibilité.
__contains__
, find
etindex
Comme promis, voici la contains
méthode:
str.__contains__('**foo**', 'foo')
retourne True
. Vous pouvez également appeler cette fonction à partir de l'instance de la super chaîne:
'**foo**'.__contains__('foo')
Mais non. Les méthodes commençant par des traits de soulignement sont considérées comme sémantiquement privées. La seule raison d'utiliser cela est lors de l'extension des fonctionnalités in
et not in
(par exemple, si le sous-classement 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')
et maintenant:
>>> 'substring' in ns
testing if "substring" in "a string with a substring inside"
True
Évitez également les méthodes de chaîne suivantes:
>>> '**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
D'autres langages peuvent ne pas avoir de méthodes pour tester directement les sous-chaînes, et vous devrez donc utiliser ces types de méthodes, mais avec Python, il est beaucoup plus efficace d'utiliser l' in
opérateur de comparaison.
Nous pouvons comparer différentes façons d'atteindre le même objectif.
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'))),
}
Et maintenant, nous voyons que l'utilisation in
est beaucoup plus rapide que les autres. Moins de temps pour faire une opération équivalente, c'est mieux:
>>> 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}
str.index
et str.find
? Sinon, comment suggéreriez-vous que quelqu'un trouve l'index d'une sous-chaîne au lieu de simplement savoir s'il existe ou non? (ou avez - vous évité moyen de les utiliser à la place de contient - alors ne pas utiliser au s.find(ss) != -1
lieu de ss in s
?)
re
module. Je n'ai pas encore trouvé d'utilisation pour str.index ou str.find moi-même dans aucun code que j'ai écrit pour le moment.
str.count
( string.count(something) != 0
). frisson
operator
version du module ?
in_
ci-dessus - mais avec un stackframe autour, donc c'est plus lent que ça: github.com/python/cpython/blob/3.7/Lib/operator.py#L153
if needle in haystack:
est l'utilisation normale, comme le dit @Michael - elle repose sur l' in
opérateur, plus lisible et plus rapide qu'un appel de méthode.
Si vous avez vraiment besoin d'une méthode au lieu d'un opérateur (par exemple, pour faire un peu bizarre key=
pour un type très particulier ...?), Ce serait 'haystack'.__contains__
. Mais comme votre exemple est destiné à être utilisé dans un if
, je suppose que vous ne pensez pas vraiment ce que vous dites ;-). Ce n'est pas une bonne forme (ni lisible, ni efficace) d'utiliser directement des méthodes spéciales - elles sont plutôt destinées à être utilisées à travers les opérateurs et les commandes intégrées qui leur sont déléguées.
in
Chaînes et listes PythonVoici quelques exemples utiles qui parlent d'eux-mêmes concernant la in
méthode:
"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]
Caveat. Les listes sont des itérables, et la in
méthode agit sur les itérables, pas seulement sur les chaînes.
["bar", "foo", "foobar"] in "foof"
:?
Si vous êtes satisfait "blah" in somestring
mais souhaitez que ce soit un appel de fonction / méthode, vous pouvez probablement le faire
import operator
if not operator.contains(somestring, "blah"):
continue
Tous les opérateurs en Python peuvent être plus ou moins trouvés dans le module opérateur, y compris in
.
Donc, apparemment, il n'y a rien de similaire pour la comparaison vectorielle. Une façon évidente de le faire en Python serait:
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
in
Ne vaut rien qui ne devrait pas être utilisé avec des listes car il effectue un balayage linéaire des éléments et est lent à comparer. Utilisez un ensemble à la place, surtout si les tests d'appartenance doivent être effectués à plusieurs reprises.
Vous pouvez utiliser y.count()
.
Il renverra la valeur entière du nombre de fois qu'une sous-chaîne apparaît dans une chaîne.
Par exemple:
string.count("bah") >> 0
string.count("Hello") >> 1
Voici votre réponse:
if "insert_char_or_string_here" in "insert_string_to_search_here":
#DOSTUFF
Pour vérifier si elle est fausse:
if not "insert_char_or_string_here" in "insert_string_to_search_here":
#DOSTUFF
OU:
if "insert_char_or_string_here" not in "insert_string_to_search_here":
#DOSTUFF
__contains__(self, item)
,__iter__(self)
et__getitem__(self, key)
dans cet ordre pour déterminer si un élément se trouve dans un contenu donné. Implémentez au moins une de ces méthodes pour rendrein
disponible votre type personnalisé.