lazy – Sam & Max http://sametmax.com Du code, du cul Wed, 23 Dec 2020 13:35:02 +0000 en-US hourly 1 https://wordpress.org/?v=4.9.7 32490438 Proposition d’un mot clé pour l’évaluation paresseuse en Python 3.7 http://sametmax.com/proposition-dun-mot-cle-pour-levaluation-paresseuse-en-python-3-7/ http://sametmax.com/proposition-dun-mot-cle-pour-levaluation-paresseuse-en-python-3-7/#comments Sun, 19 Feb 2017 17:19:51 +0000 http://sametmax.com/?p=22463 Si il y a bien une mailing-list à suivre, c’est Python-idea. Elle regorge de tout, on est y apprend sans cesse à propos de Python, la programmation en général, la gestion de communautés, etc. Mais c’est accessible pour peu qu’on soit à l’aise en anglais.

Parmi les sujets chauds du moment, il y a l’introduction, pour potentiellement Python 3.7, d’un mot clé pour évaluer paresseusement les expressions.

Je m’explique…

On a déjà plusieurs moyens de faire du lazy loading en python :

  • Le shortcut des opérateurs and et or. La partie droite ne s’exécute que si la gauche ne répond pas déjà à la question.
  • Les générateurs. Il ne sont évalués qu’au premier appel de next().
  • await : évalué seulement quand la boucle d’événement décide de passer par là.

La nouvelle proposition est quelque chose de différent : permettre de déclarer une expression arbitraire, mais qui n’est évaluée que la première fois qu’on la lit.

Ca ressemble à ça:

def somme(a, b):
    print('coucou')
    return a + b

truc = lazy somme(a, b)
print("Hello")
print(truc)

Ce qui afficherait:

Hello
coucou
3

On peut mettre ce qu’on veut après le mot clé lazy. Le code n’est exécuté qu’une fois qu’on essaye d’utiliser la variable truc.

L’usage essentiel, c’est de pouvoir déclarer du code sans chichi, comme si on allait l’utiliser maintenant. Le passer à du code qui va l’utiliser sans même avoir besoin de savoir que c’est un truc spécial. Et que tout marche à la dernière minute naturellement.

Par exemple, la traduction d’un texte dans un code Python ressemble souvent à ça :

from gettext import gettext as _
...
print(_('Thing to translate'))

Mais dans Django on déclare un champ de modèle dont on veut pouvoir traduire le nom comme ceci :

from django.utils.translation import ugettext_lazy

class Produit(models.Model):
    ...
    price = models.IntegerField(verbose_name=ugettext_lazy("price"))

La raison est qu’on déclare ce texte au démarrage du serveur, et on ne sait pas encore la langue dans laquelle on va le traduire. Cette information n’arrive que bien plus tard, quand un utilisateur arrive sur le site. Mais pour détecter toutes les chaînes à traduire, créer le fichier de traduction, construire le cache, etc., il faut pouvoir marquer la chaîne comme traductible à l’avance.

Django a donc codé ugettext_lazy et tout un procédé pour évaluer cette traduction uniquement quand une requête Web arrive et qu’on sait la langue de l’utilisateur.

Avec la nouvelle fonctionnalité, on pourrait juste faire:

from gettext import gettext as _

class Produit(models.Model):
    ...
    price = models.IntegerField(verbose_name=lazy _("price"))

Rien à coder nulle part du côté de Django, rien à savoir de plus pour un utilisateur. Ça marche dans tous les cas, pareil pour tout le monde, dans tous les programmes Python.

Bref, j’aime beaucoup cette idée qui permet de s’affranchir de pas mal de wrappers pour plein de trucs, mais aussi beaucoup aider les débutants. En effet les nouveaux en programmation font généralement des architectures basiques : pas d’injection de dépendances, pas de factories, etc. Avec lazy, même si une fonction n’accepte pas une factory, on peut quand même passer quelque chose qui sera exécuté plus tard.

Évidement ça ne dispense pas les gens de faire ça intelligemment et d’attendre des callables en paramètre. Dans le cas de Django, une meilleure architecture accepterait un callable pour verbose_name par exemple.

Mais c’est un bon palliatif dans plein de situations. Et l’avantage indiscutable, c’est que le code qui utilise la valeur paresseuse n’a pas besoin de savoir qu’elle le fait.

Les participants sont assez enthousiastes, et moi aussi, bien que tout le monde a conscience que ça pose plein de questions sur la gestion des générateurs, de locals(), et du debugging en général.

Plusieurs mots clés sont actuellement en compétition: delayed, defer, lazy. delayed est le plus utilisé, mais j’ai un penchant pour lazy.

Viendez sur la mailing list !

]]>
http://sametmax.com/proposition-dun-mot-cle-pour-levaluation-paresseuse-en-python-3-7/feed/ 14 22463