Le sourire du jour


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.

6 thoughts on “Le sourire du jour

  • kontre

    Je trouve l’implémentation plus classe aussi beaucoup moins lisible . Par contre les sets c’est magique !

  • gontran

    C’est là qu’un bon comment est pratique pour bien expliquer ce qu’il se passe.

  • foxmask

    “c’est là que je me rends compte que je vous ai moins bien réussi que le porc” :)

  • Phynx

    > Vive le duck typing.
    … et la surcharge d’opérateur : set(mode) & set(‘wa+’)
    (j’y peux rien, je craque pour la syntaxe mathématique des sets python).

  • Zanguu

    “Un set permet prend n’importe quel itérable, et créer un ensemble avec” => “Un set permet de prendre n’importe quel itérable, et de créer un ensemble avec”

    J’aime beaucoup la solution.
    Et après on se demande pourquoi les dév ne sont pas appelés des créatifs…

    @Phynx, je préfère intersection perso, parce que je me mélange toujours quand je passe entre javacript, c#, php ou sql avec le ‘&’.

Comments are closed.

Des questions Python sans rapport avec l'article ? Posez-les sur IndexError.