Sam & Max: Python, Django, Git et du cul » string http://sametmax.com Deux développeurs en vadrouille qui se sortent les doigts du code Wed, 05 Feb 2014 14:20:37 +0000 en hourly 1 http://wordpress.org/?v=3.3.1 Article retiré pour cause de grosse merde http://sametmax.com/nested-format-expansion-thats-a-swag-title-cracker/ http://sametmax.com/nested-format-expansion-thats-a-swag-title-cracker/#comments Thu, 19 Dec 2013 08:10:32 +0000 Sam http://sametmax.com/?p=8158 Désolé pour ceux qui ont reçu l’article via RSS ou email. Je le retire. C’était de la merde.

flattr this!

]]>
http://sametmax.com/nested-format-expansion-thats-a-swag-title-cracker/feed/ 4
Les expressions rationnelles en Python, parfois overkill http://sametmax.com/les-expressions-rationnelles-en-python-parfois-overkill/ http://sametmax.com/les-expressions-rationnelles-en-python-parfois-overkill/#comments Wed, 07 Aug 2013 11:40:11 +0000 Sam http://sametmax.com/?p=7042 J’adore les regex, et d’ailleurs il faudra que je fasse une série d’articles sur le sujet, un peu comme le guide de la POO.

Mais dans un langage comme Python, il y a de nombreuses solutions à mettre en oeuvre avant d’utiliser les regex.

Pour vérifier si une chaîne est dans une autre, utilisez in :

>>> 'a' in 'chat'
True
>>> 'a' in 'chien'
False
>>> 'a' in 'CHAT'.lower() # ignorer la casse
True

Pour savoir si un chaîne est au début ou à la fin, utilisez startswith() et endswith() :

>>> 'achat'.startswith('a')
True
>>> 'chat'.startswith('a')
False
>>> 'acheta'.endswith('a')
True

Pour savoir si la chaîne est d’un type particulier, utiliser les méthodes is* :

>>> '555'.isdigit()
True
>>> ''.isdigit()
False
>>> '⑦'.isdigit()
True
>>> '444'.isdecimal()
True
>>> '444.55'.isdecimal()
False
>> '⑦'.isdecimal()
False
>>> '879fds'.isalpha()
False
>>> 'fsdqfsqd'.isalpha()
True
>>> 'fsdqfsqd'.islower()
True
>>> 'fsdqFFsqd'.islower()
False
>>> '879fds'.isalnum()
True
>>> '879fds-'.isalnum()
False
>>> ' \t\n'.isspace()
True
>>> ' \t\n fdsfd'.isspace()
False

Si vous voulez manipuler la chaîne pour en extraire une partie, utilisez split() (ou rsplit(), lsplit() pour travailler sur la droite ou la gauche de la chaîne) :

>>> s = """Mais, vous savez, moi je ne crois pas qu'il y ait de bonne ou de mauvaise situation. Moi, si je devais résumer ma vie aujourd'hui avec vous, je dirais que c'est d'abord des rencontres, des gens qui m'ont tendu la main, peut-être à un moment où je ne pouvais pas, où j'étais seul chez moi. Et c'est assez curieux de se dire que les hasards, les rencontres forgent une destinée... Parce que quand on a le goût de la chose, quand on a le goût de la chose bien faite, le beau geste, parfois on ne trouve pas l'interlocuteur en face, je dirais, le miroir qui vous aide à avancer. Alors ce n'est pas mon cas, comme je le disais là, puisque moi au contraire, j'ai pu ; et je dis merci à la vie, je lui dis merci et je chante la vie, je danse la vie... Je ne suis qu'amour ! Et finalement, quand beaucoup de gens aujourd'hui me disent "Mais comment fais-tu pour avoir cette humanité ?", et bien je leur réponds très simplement, je leur dis que c'est ce goût de l'amour, ce goût donc qui m'a poussé aujourd'hui à entreprendre une construction mécanique, mais demain, qui sait, peut-être simplement à me mettre au service de la communauté, à faire le don... le don de soi."""
>>> s.split()
[u'Mais,', u'vous', u'savez,', u'moi', u'je', u'ne', u'crois', u'pas', u"qu'il", u'y', u'ait', u'de', u'bonne', u'ou', u'de', u'mauvaise', u'situation.', u'Moi,', u'si', u'je', u'devais', u'r\xe9sumer', u'ma', u'vie', u"aujourd'hui", u'avec', u'vous,', u'je', u'dirais', u'que', u"c'est", u"d'abord", u'des', u'rencontres,', u'des', u'gens', u'qui', u"m'ont", u'tendu', u'la', u'main,', u'peut-\xeatre', u'\xe0', u'un', u'moment', u'o\xf9', u'je', u'ne', u'pouvais', u'pas,', u'o\xf9', u"j'\xe9tais", u'seul', u'chez', u'moi.', u'Et', u"c'est", u'assez', u'curieux', u'de', u'se', u'dire', u'que', u'les', u'hasards,', u'les', u'rencontres', u'forgent', u'une', u'destin\xe9e...', u'Parce', u'que', u'quand', u'on', u'a', u'le', u'go\xfbt', u'de', u'la', u'chose,', u'quand', u'on', u'a', u'le', u'go\xfbt', u'de', u'la', u'chose', u'bien', u'faite,', u'le', u'beau', u'geste,', u'parfois', u'on', u'ne', u'trouve', u'pas', u"l'interlocuteur", u'en', u'face,', u'je', u'dirais,', u'le', u'miroir', u'qui', u'vous', u'aide', u'\xe0', u'avancer.', u'Alors', u'ce', u"n'est", u'pas', u'mon', u'cas,', u'comme', u'je', u'le', u'disais', u'l\xe0,', u'puisque', u'moi', u'au', u'contraire,', u"j'ai", u'pu', u';', u'et', u'je', u'dis', u'merci', u'\xe0', u'la', u'vie,', u'je', u'lui', u'dis', u'merci', u'et', u'je', u'chante', u'la', u'vie,', u'je', u'danse', u'la', u'vie...', u'Je', u'ne', u'suis', u"qu'amour", u'!', u'Et', u'finalement,', u'quand', u'beaucoup', u'de', u'gens', u"aujourd'hui", u'me', u'disent', u'"Mais', u'comment', u'fais-tu', u'pour', u'avoir', u'cette', u'humanit\xe9', u'?",', u'et', u'bien', u'je', u'leur', u'r\xe9ponds', u'tr\xe8s', u'simplement,', u'je', u'leur', u'dis', u'que', u"c'est", u'ce', u'go\xfbt', u'de', u"l'amour,", u'ce', u'go\xfbt', u'donc', u'qui', u"m'a", u'pouss\xe9', u"aujourd'hui", u'\xe0', u'entreprendre', u'une', u'construction', u'm\xe9canique,', u'mais', u'demain,', u'qui', u'sait,', u'peut-\xeatre', u'simplement', u'\xe0', u'me', u'mettre', u'au', u'service', u'de', u'la', u'communaut\xe9,', u'\xe0', u'faire', u'le', u'don...', u'le', u'don', u'de', u'soi.']
>>> s.split()[0]
u'Mais,'
>>> s.split()[5:7]
[u'ne', u'crois']
>>> s.split(',')
[u'Mais', u' vous savez', u" moi je ne crois pas qu'il y ait de bonne ou de mauvaise situation. Moi", u" si je devais r\xe9sumer ma vie aujourd'hui avec vous", u" je dirais que c'est d'abord des rencontres", u" des gens qui m'ont tendu la main", u' peut-\xeatre \xe0 un moment o\xf9 je ne pouvais pas', u" o\xf9 j'\xe9tais seul chez moi. Et c'est assez curieux de se dire que les hasards", u' les rencontres forgent une destin\xe9e... Parce que quand on a le go\xfbt de la chose', u' quand on a le go\xfbt de la chose bien faite', u' le beau geste', u" parfois on ne trouve pas l'interlocuteur en face", u' je dirais', u" le miroir qui vous aide \xe0 avancer. Alors ce n'est pas mon cas", u' comme je le disais l\xe0', u' puisque moi au contraire', u" j'ai pu ; et je dis merci \xe0 la vie", u' je lui dis merci et je chante la vie', u" je danse la vie... Je ne suis qu'amour ! Et finalement", u' quand beaucoup de gens aujourd\'hui me disent "Mais comment fais-tu pour avoir cette humanit\xe9 ?"', u' et bien je leur r\xe9ponds tr\xe8s simplement', u" je leur dis que c'est ce go\xfbt de l'amour", u" ce go\xfbt donc qui m'a pouss\xe9 aujourd'hui \xe0 entreprendre une construction m\xe9canique", u' mais demain', u' qui sait', u' peut-\xeatre simplement \xe0 me mettre au service de la communaut\xe9', u' \xe0 faire le don... le don de soi.']
>>> s.split('.')
[u"Mais, vous savez, moi je ne crois pas qu'il y ait de bonne ou de mauvaise situation", u" Moi, si je devais r\xe9sumer ma vie aujourd'hui avec vous, je dirais que c'est d'abord des rencontres, des gens qui m'ont tendu la main, peut-\xeatre \xe0 un moment o\xf9 je ne pouvais pas, o\xf9 j'\xe9tais seul chez moi", u" Et c'est assez curieux de se dire que les hasards, les rencontres forgent une destin\xe9e", u'', u'', u" Parce que quand on a le go\xfbt de la chose, quand on a le go\xfbt de la chose bien faite, le beau geste, parfois on ne trouve pas l'interlocuteur en face, je dirais, le miroir qui vous aide \xe0 avancer", u" Alors ce n'est pas mon cas, comme je le disais l\xe0, puisque moi au contraire, j'ai pu ; et je dis merci \xe0 la vie, je lui dis merci et je chante la vie, je danse la vie", u'', u'', u' Je ne suis qu\'amour ! Et finalement, quand beaucoup de gens aujourd\'hui me disent "Mais comment fais-tu pour avoir cette humanit\xe9 ?", et bien je leur r\xe9ponds tr\xe8s simplement, je leur dis que c\'est ce go\xfbt de l\'amour, ce go\xfbt donc qui m\'a pouss\xe9 aujourd\'hui \xe0 entreprendre une construction m\xe9canique, mais demain, qui sait, peut-\xeatre simplement \xe0 me mettre au service de la communaut\xe9, \xe0 faire le don', u'', u'', u' le don de soi', u'']

Et n’oubliez pas que vous pouvez appeler join() derrière.

Si vous devez altérer la chaîne, utilisez strip() (et rstrip(), lstrip()) ou replace() :

>>> "Les nouilles cuisent au jus de canne".replace('noui', 'coui').replace('cui', 'nui').replace('jus', 'cul').replace('canne', 'jeanne')
u'Les couilles nuisent au cul de jeanne'
>>> "                               .                       ".strip()
u'.'
>>> "===                               .                       ======".strip("= ")
u'.'

En plus, les chaînes sont itérables, indexables et sliceables, donc :

>>> s = """And I will strike down upon thee with great vengeance and furious anger those who attempt to poison and destroy my brothers. And you will know my name is the Lord when I lay my vengeance upon you!"""
>>> s[3:30:3]
u' wltkdnp '
>>> s.split()
[u'And', u'I', u'will', u'strike', u'down', u'upon', u'thee', u'with', u'great', u'vengeance', u'and', u'furious', u'anger', u'those', u'who', u'attempt', u'to', u'poison', u'and', u'destroy', u'my', u'brothers.', u'And', u'you', u'will', u'know', u'my', u'name', u'is', u'the', u'Lord', u'when', u'I', u'lay', u'my', u'vengeance', u'upon', u'you!']
>>> s[0]
u'A'
>>> ''.join([(l.upper() if i % 2 else l) for i, l in enumerate(s)])
u'ANd I wIlL StRiKe dOwN UpOn tHeE WiTh gReAt vEnGeAnCe aNd fUrIoUs aNgEr tHoSe wHo aTtEmPt tO PoIsOn aNd dEsTrOy mY BrOtHeRs. AnD YoU WiLl kNoW My nAmE Is tHe LOrD WhEn I lAy mY VeNgEaNcE UpOn yOu!'

Bref, avant de sortir le bazooka, souvenez-vous que vous avez un arsenal déjà très approprié pour traiter les strings, dont les perfs seront en plus probablement meilleures.

flattr this!

]]>
http://sametmax.com/les-expressions-rationnelles-en-python-parfois-overkill/feed/ 14
% ou format() en Python ? http://sametmax.com/ou-format-en-python/ http://sametmax.com/ou-format-en-python/#comments Fri, 21 Jun 2013 10:47:41 +0000 Sam http://sametmax.com/?p=6416 On a réçu un mail du genre :

Salut les mecs!

Je me demandais si il valait mieux utiliser format() ou % quand on veut insérer une variable dans une chaîne?
Je comprend pas vraiment quelle est la différence entre les deux…l’un est-il plus rapide? Plus fiable?

Merci les mecs!

Donc je suppose que d’autres personnes se posent la même question, du coup je poste ça là une bonne fois pour toute.

En résumé :

% c’est la manière de faire de Python 2, format(), c’est du Python 3. Mais format() a été backporté en Python 2.6.

Du coup, utilisez toujours format(), ça facilite le portage du code et ça donne de bonnes habitudes. Les mecs comme moi ont encore du mal (je me force) et parfois laissent échapper un % par réflexe, surtout que c’est plus court à taper et qu’on est des fainéants. D’ailleurs les anciens articles du blogs le montrent. C’est pas une excuse. format() pour tout le monde, et que ça saute !

flattr this!

]]>
http://sametmax.com/ou-format-en-python/feed/ 16
Le piège de la méthode strip() des chaînes en Python http://sametmax.com/le-piege-de-la-methode-strip-des-chaines-en-python/ http://sametmax.com/le-piege-de-la-methode-strip-des-chaines-en-python/#comments Mon, 01 Oct 2012 13:27:45 +0000 Sam http://sametmax.com/?p=2309 strip(), et ses acolytes lstrip() et rstrip(), ne retirent pas la chaîne de caractères aux extrémités d'une autre chaîne de caractères.]]> strip(), et ses acolytes lstrip() et rstrip(), ne retirent pas la chaîne de caractères aux extrémités d’une autre chaîne de caractères.

Elles retirent des extrémités toutes lettres qui sont dans la chaînes passée en paramètre. La nuance est subtile, mais c’est la différence entre ça:

>>> "# ##  # test ".strip('# ') # comportement attendu mais faux
'##  # test '

Et ça:

>>> "# ##  # test ".strip('# ') # comportement réel
'test'

flattr this!

]]>
http://sametmax.com/le-piege-de-la-methode-strip-des-chaines-en-python/feed/ 6
Comment marchent les “raw strings” en Python ? http://sametmax.com/comment-marchent-les-raw-strings-en-python/ http://sametmax.com/comment-marchent-les-raw-strings-en-python/#comments Tue, 06 Mar 2012 16:13:04 +0000 Sam http://sametmax.com/?p=241 Dans certains tutos, notamment ceux sur les expressions rationelles, on recommande d’utiliser les “raw strings”, en mettant un “r” devant la déclaration de la chaîne de caractères.

Par exemple:

'1?\d\d?'

Devient:

r'1?\d\d?'

A quoi cela sert-il ?

Voyons d’abord à quoi cela ne sert pas

  • créer un type de string particulier. Il n’y a rien de tel qu’un type “raw string” en Python. La chaîne résultante est une chaîne ordinaire.
  • créer une chaîne destinée aux regex. On utilise particulièrement la notation ‘r’ avec les regex, mais ce n’est pas un type dédié.

‘r’ est juste un modifieur, une sorte de paramètre. En effet, quand vous écrivez 'Salut !\n', vous n’écrivez PAS la chaîne “Salut ![LB]“. Vous dites à Python de créer un objet chaîne, de la même manière que vous lui demanderiez une instanciation en faisant MaClasse().

'Salut !\n' est juste une notation, pas la chaîne elle même. Cette notation dit à Python: À partir de cet instant dans le programme, tu vas créer un objet chaîne en mémoire, et voici les paramètres que je te donne pour le créer. La notation étant différente, on a l’illusion d’écrire la chaîne soi-même, mais en fait ce n’est pas différent d’un appel de fonction.

Quand vous faites 'Salut !\n', vous dites plus précisément à Python: Instancie un objet de type string, met les caractères S, a, l, u, t, espace et point d’exclamtion dedans, suivi d’un saut de ligne. Cette notation, pour se faciliter la vie, permet de décrire “saut de ligne” en écrivant '\n'. Python analyse donc votre chaîne, cherche toutes les combinaions de charactères spéciaux comme '\n', '\t', etc, et quand il créer l’objet en mémoire, il ajoute un saut de ligne ou une tabulation, et pas les caractères ‘\’ puis ‘n’ ou ‘t’.

Que se passe-t-il si vous voulez réellement ajouter ‘\’ et ‘n’ ?

Il faut utiliser une autre notation, l’échappement. On utilise un ‘\’ pour dire à Python: créer cet objet en mémoire, mais à cet endroit, ne tient pas compte de la combinaison de caractères spéciaux.

Ceci affiche un saut de ligne: print '\n est le caractère de saut de ligne'

Ceci affiche ‘\’, ‘n’ puis la phrase: print '\\n est le caractère de saut de ligne'

Mais il existe des cas où c’est très fastidieux et illisible. Notamment les expression rationnelles, où les ‘\’ font partie intégrante du système.

Un exemple simple, vous voulez “C:\Program Files” dans une phrase:

Votre regex devra contenir ‘\P’. Saut qu’en regex, ‘\P’ est un symbole special, donc il faut l’échapper, vous aurez donc ‘\\P’. Sauf qu’en Python, il faut échapper les ‘\’ pour qu’il ne soient pas considérés comme caractères spéciaux, vous aurez donc ‘\\\\P’. Sur une regex complexe, ça devient vitre très moche, et très dur à déboguer.

C’est là qu’intervient le modifieur ‘r’, qui précise à Python: quand tu vas créer cette chaîne en mémoire, met ces caractères dedans littéralement et considère qu’il n’y a aucune combinaison de caractères spéciaux.

En clait r'\n' sera ‘\’ puis ‘n’. Python ne va tout simplement par parser la chaîne, il va l’utiliser litteralement, d’où le “raw” string.

Il n’y a donc rien de spécial à dans une chaîne créée avec le modifieur ‘r’, c’est une chaîne normale, qui est instanciée sans réfléchir par Python, sans chercher à être malin et comprendre des notations spéciales.

Ca ne veut pas dire qu’on ne peut pas avoir des sauts de ligne dans une chaîne créée avec ‘r’:

>>> print r"""1 + 1 = 
... 42"""
1 + 1
42

Ca veut juste dire que les notations spéciales ne seront pas analysées:

>>> print '1 + 1 =\n 42'
1 + 1 =
42
>>> print r'1 + 1 =\n 42'
1 + 1 =\n 42

Il est facile de s’embrouiller les pinceaux à cause du shell Python:

>>> 'test\n'
'test\n'
>>> r'test\n'
'test\\n'
>>> print 'test\n'
test
 
>>> print r'test\n'
test\n

Il faut savoir que quand on affiche un objet sans utiliser print dans le shell, ce dernier essaye de vous afficher une représentation de l’objet de telle sorte qu’il puisse être copié et collé, et recréer le même objet. En revanche, print va afficher du texte formatté pour être lisible par un humain.

flattr this!

]]>
http://sametmax.com/comment-marchent-les-raw-strings-en-python/feed/ 3