Python >> Tutoriel Python >  >> Python

Tutoriel Python endswith() – Pouvons-nous utiliser des expressions régulières ?

Lors de la refactorisation de mon code Python, j'ai pensé à la question suivante.

Pouvez-vous utiliser une expression régulière avec la méthode Python endswith() ?

La réponse simple est non parce que si vous pouvez utiliser une regex, vous n'aurez même pas besoin de endswith() ! Utilisez plutôt le re.match(regex, string) fonction du re module. Par exemple, re.match("^.*(coffee|cafe)$", tweet) vérifie si une chaîne d'une seule ligne stockée dans la variable tweet se termine soit par 'coffee' ou 'cafe' .

En fait, je me suis rendu compte qu'en utilisant une regex avec le endswith() méthode n'a pas de sens. Pourquoi? Si vous souhaitez utiliser des expressions régulières, utilisez les fonctions du re module. C'est pour cela qu'ils ont été créés ! Les expressions régulières sont infiniment plus puissantes que le endswith() méthode !

(Temps de lecture 6 minutes — ou regardez la vidéo pour en savoir plus sur le string.endswith() méthode)

Voulez-vous maîtriser la superpuissance des regex ? Découvrez mon nouveau livre La façon la plus intelligente d'apprendre les expressions régulières en Python avec l'approche innovante en 3 étapes pour un apprentissage actif :(1) étudiez un chapitre de livre, (2) résolvez un puzzle de code et (3) regardez une vidéo de chapitre éducatif.

Comment fonctionne la méthode Python endswith() ?

Voici un aperçu du string.endswith méthode :

str.endswith(prefix[, start[, end]])
prefix obligatoire Valeur de chaîne à rechercher en début de chaîne str .
start facultatif Index de la première position où le préfixe doit être vérifié. Par défaut :start=0 .
end facultatif Index de la dernière position où le préfixe doit être vérifié. Par défaut :end=len(str)-1 .

Regardons quelques exemples utilisant le Python endswith méthode. Dans chacun d'eux, je modifierai le code pour montrer différents cas d'utilisation. Commençons par le scénario le plus basique.

Python endswith() Exemple le plus basique

Supposons que vous ayez une liste de chaînes où chaque chaîne est un tweet.

tweets = ["to thine own self be true",
          "coffee break python",
          "i like coffee"]

Disons que vous travaillez dans l'industrie du café et que vous souhaitez obtenir tous les tweets qui se terminent par la chaîne "coffee" . Vous utiliserez le endswith méthode avec un seul argument :

>>> for tweet in tweets:
...   if tweet.endswith("coffee"):
...       print(tweet)
i like coffee

Le endswith method a deux arguments facultatifs :start et end . Vous pouvez utiliser ces deux arguments pour vérifier si une sous-chaîne de la chaîne d'origine se termine par votre argument. Besoin d'un exemple qui explique les deux arguments ?

Python endswith() Arguments facultatifs

Le endswith method a deux arguments facultatifs :start et end . Vous pouvez les utiliser pour définir une plage d'indices à vérifier. Par défaut, endswith vérifie toute la chaîne. Regardons quelques exemples.

L'argument start indique endswith() par où commencer la recherche. La valeur par défaut est 0, c'est-à-dire qu'elle commence au début de la chaîne. Ainsi, le code suivant renvoie le même résultat que ci-dessus :

>>> for tweet in tweets:
...   if tweet.endswith("coffee", 0):
...       print(tweet)
i like coffee

Que se passe-t-il si nous définissons start=8 ?

>>> for tweet in tweets:
...   if tweet.endswith("coffee", 8):
...       print(tweet)

Pourquoi n'imprime-t-il rien ? En appelant le find() méthode, nous voyons que la sous-chaîne 'coffee' commence à l'index 7.

>>> 'i like coffee'.find('coffee')
7

Mais tweet.endsswith("coffee", 8) commence à chercher à partir de l'index 8. Le résultat est donc False et rien n'est imprimé.

Ajoutons un autre argument - le end index – jusqu'au dernier extrait :

>>> for tweet in tweets:
...   if tweet.startswith("coffee", 7, 9):
...       print(tweet)


Rien n'est imprimé sur la console. En effet, nous ne recherchons que sur deux caractères - en commençant à l'index 7 (inclus) et en terminant à l'index 9 (exclusif). Mais nous recherchons 'coffee' et il fait 6 caractères. Comme 6> 2, endswith() ne trouve aucune correspondance et ne renvoie donc rien.

Maintenant que vous savez tout sur le endswith de Python méthode, revenons à notre question initiale :

Puis-je utiliser une expression régulière avec la méthode Python endswith() ?

Non. Le endswith() La méthode n'autorise pas les expressions régulières. Vous ne pouvez rechercher qu'une chaîne.

Une expression régulière peut décrire un ensemble infini de chaînes correspondantes. Par exemple, '*A' correspond à tous les mots se terminant par 'A' . Cela peut être coûteux en calcul. Donc, pour des raisons de performances, il est logique que endswith() n'accepte pas les expressions régulières.

Article connexe : Python Regex Superpower - Le guide ultime

Mais est-il également vrai que endswith n'accepte qu'une seule chaîne comme argument ? Pas du tout. Il est possible de faire ce qui suit :

Python endswith() Tuple - Vérifier plusieurs chaînes

>>> for tweet in tweets:
...   if tweet.endswith(("coffee", "python")):
...       print(tweet)
coffee break python
i like coffee

Cet extrait imprime toutes les chaînes qui se terminent par "coffee" ou "python" . C'est assez efficace aussi. Malheureusement, vous ne pouvez vérifier qu'un ensemble fini d'arguments. Si vous devez vérifier un ensemble infini, vous ne pouvez pas utiliser cette méthode.

Que se passe-t-il si je passe une expression régulière à endswith() ?

Vérifions si un tweet se termine par n'importe quelle version du "coffee" chaîne de caractères. En d'autres termes, nous voulons appliquer la regex ".+coff*" . Cela correspond avidement à n'importe quel caractère une ou plusieurs fois, puis 'coff' plus un nombre arbitraire de caractères. Ainsi, nous faisons correspondre les chaînes qui se terminent par "coffee" , "coffees" et "coffe" .

>>> tweets = ["to thine own self be true",
              "coffee break python",
              "i like coffee",
              "i love coffe",
              "what's better than one coffee? two coffees!"]

>>> for tweet in tweets:
        if tweet.endswith(".+coff*"):
          print(tweet)
# No output :(

Cela ne fonctionne pas. Dans les expressions régulières, * est un joker et représente n'importe quel caractère. Mais dans le endswith() méthode, cela signifie simplement le caractère étoile * . Étant donné qu'aucun des tweets ne se termine par la chaîne littérale "coff*" , Python n'imprime rien à l'écran.

Alors vous pourriez demander :

Quelles sont les alternatives à l'utilisation d'expressions régulières dans endswith() ?

Il existe une alternative simple et propre :utilisez le re module. Il s'agit du module intégré de Python conçu pour fonctionner avec des expressions régulières.

>>> import re
>>> tweets = ["to thine own self be true",
              "coffee break python",
              "i like coffee",
              "i love coffe",
              "what's better than one coffee? two coffees!"]
# Success!
>>> for tweet in tweets:
        if re.match(".+coff*", tweet):
          print(tweet)
i like coffee
i love coffe
what’s better than one coffee? two coffees! 

Succès! Nous avons maintenant imprimé tous les tweets que nous attendions. Autrement dit, tous les tweets qui se terminent par "coff" plus un nombre arbitraire de caractères.

Notez que cette méthode est assez lente. L'évaluation des expressions régulières est une opération coûteuse. Mais la clarté du code s'est améliorée et nous avons obtenu le résultat que nous voulions. Lent et efficace vaut mieux que rapide et infructueux.

La fonction re.match() prend deux arguments. Tout d'abord, l'expression régulière à rechercher. Deuxièmement, la chaîne que vous souhaitez rechercher. Si une sous-chaîne correspondante est trouvée, elle renvoie True . Sinon, il renvoie False . Dans ce cas, il renvoie False pour "to thine own self be true" et "coffee break python" . Il renvoie True pour le reste.

Résumons donc l'article.

Pouvez-vous utiliser une expression régulière avec la méthode Python endswith() ?

Non, vous ne pouvez pas utiliser une expression régulière avec le Python endswith fonction. Mais vous pouvez utiliser le module d'expression régulière Python re Au lieu. C'est aussi simple que d'appeler la fonction match(s1, s2) . Ceci trouve l'expression régulière s1 dans la chaîne s2 .

Python se termine par la liste()

Étant donné que nous pouvons passer un tuple à endswith() , que se passe-t-il si nous passons une liste ?

>>> s = 'cobra'
>>> if s.endswith(['a', 'b', 'c']):
        print('yay!')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: endswith first arg must be str or a tuple of str, not list

Python lève un TypeError . Nous ne pouvons passer qu'un tuple à endswith() . Donc, si nous avons une liste de préfixes que nous voulons vérifier, nous pouvons appeler tuple() avant de le passer à endswith .

>>> if s.endswith(tuple(['a', 'b', 'c'])):
        print('yay!')
yay!

Cela fonctionne bien et est très performant en termes de performances. Pourtant, l'une des principales caractéristiques de Python est sa flexibilité. Est-il donc possible d'obtenir le même résultat sans changer notre liste de lettres en un tuple ? Bien sûr que ça l'est !

Nous avons deux options :

  1. any() + compréhension de la liste
  2. any() + map()

Le any() La fonction est un moyen de combiner des instructions logiques ou ensemble. Il prend un argument - un itérable d'instructions conditionnelles. Donc au lieu d'écrire

if s.endswith('a') or s.endswith('b') or s.endswith('c'):
    # some code

Nous écrivons

# any takes 1 argument - an iterable
if any([s.endswith('a'),
        s.endswith('b'),
        s.endswith('c')]):
    # some code

C'est beaucoup plus agréable à lire et particulièrement utile si vous utilisez de nombreuses instructions mathématiques. Nous pouvons améliorer cela en créant d'abord une liste de conditions et en la transmettant à any() .

letters = ['a', 'b', 'c']
conditions = [s.endswith(l) for l in letters]

if any(conditions):
    # do something

Alternativement, nous pouvons utiliser map au lieu d'une compréhension de liste

letters = ['a', 'b', 'c']
if any(map(s.endswith, letters)):
    # do something

Les deux ont le même résultat. Nous préférons personnellement les compréhensions de liste et pensons qu'elles sont plus lisibles. Mais choisissez celui que vous préférez.

Humour Regex

Cours Python Regex

Les ingénieurs de Google sont passés maîtres dans l'expression régulière. Le moteur de recherche Google est un énorme moteur de traitement de texte qui extrait la valeur de milliers de milliards de pages Web.

Les ingénieurs de Facebook sont des maîtres des expressions régulières. Les réseaux sociaux comme Facebook, WhatsApp et Instagram connectent les humains via des messages texte .

Les ingénieurs d'Amazon sont des maîtres des expressions régulières. Les géants du commerce électronique expédient des produits basés sur des descriptions de produits textuelles . Les expressions régulières dominent le jeu lorsque le traitement de texte rencontre l'informatique.

Si vous souhaitez également devenir un maître des expressions régulières, consultez le cours Python regex le plus complet au monde :