PROJET AUTOBLOG


Sam & Max: Python, Django, Git et du cul

Site original : Sam & Max: Python, Django, Git et du cul

⇐ retour index

Le sourire du jour

mardi 4 mars 2014 à 11:29

Je me baladais dans le code source de path.py, et je suis tombé sur l’auteur essayant de résoudre le problème suivant :

“Soit une chaine ‘mode’ représentant le mode d’ouverture du fichier, détecter si le fichier est demandé à être ouvert en écriture et dans ce cas lever une exception”

L’implémentation naïve serait:

for letter in mode:
    if letter in 'wa+':
        raise ValueError('Only read-only file modes can be used')

Une implémentation un peu plus classe serait :

if any(letter for letter in mode if letter in 'wa+'):
    raise ValueError('Only read-only file modes can be used')

Mais l’auteur a choisit d’utiliser les sets, qui sont exactement fait pour ça. Et la solution est simple et élégante:

if set(mode).intersection('wa+'):
    raise ValueError('Only read-only file modes can be used')

Je sais, il m’en faut pas grand chose pour être heureux.


Edit: explication demandée en comments :)

Un set permet de prendre n’importe quel itérable, et créer un ensemble avec. Il est capable de faire toutes les opérations ensemblistes (union, différence, etc) entre lui-même et un autre itérable.

Dans notre cas, si le mode contient un flag qui implique l’écriture, voici ce que ça donne en détails :

>>> mode = 'wb'
>>> set_de_mode = set(mode)
>>> set_de_mode
set([u'b', u'w'])
>>> set_de_mode.intersection('wa+')
set([u'w'])

On se retrouve donc avec un élément dans le set résultant de l’intersection. Un set non vide a une valeur True dans un contexte booléen en Python, donc la conditionif set(mode).intersection('wa+'): sera remplie.

A l’inverse, si il n’y a pas de flag qui implique l’écriture :

>>> set('r').intersection('wa+')
set([])

On obtient un set vide, qui vaut False dans un contexte booléen.

Tout ceci marche car les chaînes de caractères sont itérables en Python, et que les sets acceptent n’importe quel itérable. Vive le duck typing.

flattr this!