Parution de Python 3.5

Posté par . Édité par Benoît Sibaud, palm123, Snark, M5oul, tankey, jcr83, Davy Defaud, Nÿco, Pierre Jarillon et Lucas. Modéré par Benoît Sibaud. Licence CC by-sa
Tags :
55
22
sept.
2015
Python

La version officielle de Python 3.5 est parue le 13 septembre 2015, presque un an après la publication de la Python Enhancement Proposals (PEP) 0478 qui annoncait le planning de cette dernière, et un peu plus de 8 mois après la première alpha (du 8 février 2015).

Python

Voyons dans la suite de cette dépêche les nouveautés introduites par cette version.

Sommaire

PEP 441 : amélioration du support des applications ZIP

L'interpréteur Python peut, depuis la version 2.6, exécuter des répertoires ou des fichiers archives au format zip. Lorsque l'interpréteur est appelé avec l'argument idoine, ce dernier ajoute le répertoire, ou le contenu du fichier zip, à sys.path, et exécute le module __ main __ contenu (dans le répertoire et le fichier zip).

Cela permet de publier de manière simple un programme python complexe via un unique fichier.
Cette fonctionnalité n'est pas très utilisée. La raison la plus couramment invoquée est que, malgré sa présence dès Python 2.6, elle n'a pas été très médiatisée. L'autre problème vient également du fait que l'installateur Windows n'enregistre pas de type spécifique pour cette fonctionnalité. Cela posait problème, puisqu'un fichier (.zip) est souvent perçu comme un fichier à décompresser, alors qu'un fichier Python (.py) est plutôt vu comme un fichier texte lisible.

Pour remédier à ce problème, deux nouvelles extensions voient le jour :
- .pyz, pour les applications en mode console ;
- pyzw, pour les applications en mode fenêtré (pas d’ouverture d’une console).

Exemple pratique

Pour créer de tels fichiers, il faut utiliser le module zipapp, qui définit, entre autres, la fonction suivante :

create_archive(source, target=None, interpreter=None, main=None)

Cette dernière est assez explicite. Prenez un répertoire où se situe un code source Python, avec un fichier __ main __.py qui sera le point de lancement de l'application.
Maintenant, très simplement, utilisez la commande :

python -m zipapp directory -o myUberConsoleApp.pyz

Et vous voilà avec un fichier myUberConsoleApp.pyz unique à distribuer.
Un clic (double ou simple, selon votre configuration), ou un simple appel à python myUberConsoleApp.pyz lancera votre über programme.

PEP 448 : dépaquetage généralisé (Additional Unpacking Generalizations)

Dur à traduire, mais plus aisé à comprendre. C'est en particulier deux limites qui ont été supprimées.
1. Désormais, la limitation d'un seul argument à « dépaqueter » est levée. Vous pouvez en utiliser autant que vous le désirez, tant pour les fonctions que pour les listes, les tuples ou les dictionnaires. (Note que le dernier argument « dépaqueté » écrase le précédent en cas de conflit).
2. Il est désormais possible de « dépaqueter » dans les déclarations d'éléments itérables (tuple/n-uplet, list/liste, set/collection, dict/dictionnaire).

Exemple pratique

Vous avez deux listes d'arguments :

my_args_1={'site':"My_Crosoft",'operation':"dos"}
my_args_2={'botnet_to_user':4,'method':"brute_force"}

# Avant, mais ça, c'était avant, vous deviez faire:
my_args_1.update(my_args_2)
do_the_job(**my_args_1)
# ou bien
from collections import ChainMap
do_the_job(**ChainMap(my_args_1, my_args_2))

#Désormais, un simple:
do_the_job(**my_args_1,**my_args_2) suffira.

C'est ça, la pureté syntaxique de Python. Moins de sucre, pour autant de cholestérol.

# Avant :
dict={"b":2,"c":3}
result={"a":1}
result.update(dict)

tab=[2,3,4]
result=[1,] + tab

# En 3.5 :
dict={"b":2,"c":3}
result={"a":1,**dict}

tab=[2,3,4]
result=[1,*tab]

et ça marche pour les *args aussi.

PEP 461 : ajout du formateur % pour les octets et tableaux d'octets

Python 3, c'est bien, mais pas pour tout le monde. En particulier, avec son unicodification généralisée, str et bytes (octets) ne voulaient plus se causer. Un bien (unicode pour les str) pour un mal (les bytes ne permettent pas le formatage direct). Mais pourquoi donc, de nos jours, utiliser les bytes et le formatage direct ? Pour un grand nombre de protocoles, pour l'écriture de fichier binaire, et pour plein d'autres choses souvent utiles. Et le str de Python 2.x était pour cela, ma foi, fort pratique.
Malgré quelques réticences à rendre les bytes « formattables » grâce à l'opérateur %, cela revenant à réintroduire les problèmes de Python 2.x dans Python 3, la simplification induite pour toute une gamme de programme, fut un argument fort et suffisamment pertinent pour son implémentation dans Python 3.5.

Exemple pratique

b"%x" % val
# remplacant avantageusement le 
("%x" % val).encode("ascii")

# ou encore, plus parlant:
>>> b'%#4x' % 10
' 0xa'

>>> b'%04X' % 10
'000A'

PEP 471 : la fonction os.scandir(), un itérateur meilleur et plus rapide sur un répertoire

Il y a toute une histoire et polémique derrière cette nouveauté, qui concerne Python 2.x, mais nous y reviendrons après vous avoir présenté la chose.

os.walk() comme chacun le sait, permet d'obtenir un itérateur sur la liste des fichiers et dossiers d'un répertoire. Cette fonction est relativement lente, pour une raison toute simple : son implémentation exécute un appel stat() ou GetFileAttributes() sur chaque entrée pour déterminer si cette dernière est un fichier ou un répertoire. Or, la fonction (FindNextFile / readdir) retourne directement cette information, ce qui rend inutile l'appel à stat().
C'est ainsi qu'est né os.scandir(), un itérateur théoriquement plus rapide.

Cette suppression a permis d'obtenir des gains de vitesse assez importants, puisque l'on parle d'une fonction désormais 8 à 9 fois plus rapide sous Windows et 2 à 3 fois plus rapide sur un système POSIX. (Avec une pointe à 36 fois plus rapide en NFS sous Windows, comme l'indiquent ces benchmarks, avec du NFS sans cache sur les propriétés des fichiers, qui reste la configuration par défaut)

La polémique

La polémique est née du portage de cette "correction" dans Python 2.x, normalement en mode "maintenance". C'est une optimisation et non une correction de bug, donc il est difficile de comprendre qu'on porte cette amélioration.
La ligne directrice était : vous voulez l'amélioration, venez sur Python 3.x. La branche 2.x ne doit recevoir que des corrections de bogues. Cette modification relativement triviale permettrait d'améliorer Python2.7, encore largement utilisé. De fait, le module scandir existe pour Python 2.6+, mais n'est pas inclus à la bibliothèque standard, comme dans Python 3.5,

PEP 475 : réessayer les appels système ayant échoué avec un EINTR

Encore une fonction intéressante. Ici, on parle de gérer de manière la plus fine possible les signaux envoyés par l'OS. Par exemple, ce fameux Break/SIGINT (via Ctrl-C) qui interrompt (ou le devrait) tout traitement.
En Python 3.4, pour gérer une exception InterruptError, cela doit être fait et dupliqué partout. Or, bien peu de modules le font vraiment. Par exemple, voici comment écrire une simple lecture de fichier, si l'on refuse d'être interrompu :

while True:
    try:
        data = file.read(size)
        break
    except InterruptedError:
        continue

Couvrir l'ensemble des modules pour gérer correctement cette exception est complexe et long, ce qui a conduit à un état de fait : peu de modules gèrent ce InterruptedError. (asyncio,asyncore,io , _pyio, multiprocessing, selectors, socket, socketserver, subprocess sont les seuls modules à le gérer).

D'autres langages de programmation traitent le problème différemment, à un niveau plus bas, ce qui permet aux bibliothèques et aux applications de s'en abstraire.

Python décide d'aller lui aussi dans cette voie. S'il est toujours possible d'attacher une fonction à un signal, cette dernière sera appelée et du résultat dépendra la levée ou non d'une exception. Si aucune exception n'est levée, alors Python recommencera l'opération système sur lequel il s'était à l'origine arrêté, et si cette opération système disposait d'un timeout, ce dernier sera recalculé.

PEP 479 : modification de la gestion de StopIteration dans les générateurs

L'exception StopIteration combinée avec des générateurs est souvent source d'ennuis, surtout lorsqu'il est nécessaire de déboguer, avec l'introduction de bugs silencieux.
Cette PEP clarifie donc un point essentiel, qui est que pour quitter un générateur, il faut utiliser un return et non lever une exception de type StopIteration.

Désormais, si une exception de type StopIteration survient dans un générateur, elle est remplacée par une RuntimeError, qui fait échouer le prochain appel à next(), et permet de dépiler correctement l’exception.

Ce changement est important, puisqu'il semble que de nombreux codes utilisaient cette exception pour sortir d'un itérateur. Il sera donc nécessaire de faire attention à vos sources lors d'un passage à la version 3.5

PEP 484 : module typing, le nouveau standard pour les annotations de typage

Je reste dubitatif devant cette PEP, même si cette dernière vient de Guido van Rossum lui-même.
Les annotations existent depuis Python 3, et étaient jusqu'à présent relativement souples, permettant d'utiliser n'importe quel objet, qui sera stocké dans l'attribut annotations.
Cela ne sert à rien (l'interpréteur n'utilise pas cette information), c'est du sucre syntaxique. Éventuellement, cela permet de mieux documenter les fonctions.

# Cette fonction prend en argument une chaîne de caractères et en retourne une.
def upper_vowel(words: str) -> str:
    return "".join([(lambda a: a.upper() if a in "aeiouy" else a)(letter) for letter in words])

Python 3.5 vient donc restreindre et préciser le rôle des annotations. Par convention, elles deviennent réservées au typage. Cela consiste à indiquer le type des arguments et préciser également le type des retour des fonctions.

Pour cela un module typing a été créé pour permettre de définir des types génériques.

Conscient que ces annotations peuvent nuire à la lisibilité du code, nous obtenons l'ajout de fichiers Stub, qui permettent de créer des annotations pour un fichier source dans un fichier séparé .pyi, avec une syntaxe spécifique, qui reprend uniquement le nom des classes et des fonctions annotés.

PEP 485 : math.isclose(), a function for testing approximate equality

Lorsqu'on en vient aux flottants et aux approximations, il est nécessaire de toujours faire attention aux inégalités. Bref, cela n'est pas spécifique à Python, mais à la représentation des flottants.

math.isclose(a, b, rel_tol=1e-9, abs_tol=0.0)

# Utilisable ainsi:
math.isclose(1.1,1.2,0.1) =>True

Par défaut, la valeur relative de test est de 1e-9 (c'est explicité dans l'aide de la fonction)

À connaître :

NaN est considéré comme n'étant proche d'aucune autre valeur, même NaN:
math.isclose(NaN,NaN) => False
math.isclose(NaN,0) => False

Inf et -Inf ne sont proches que d'eux-mêmes.

PEP 488 : suppression des fichiers .pyo

Les fichiers .pyo disparaissent…
Mais pas d'inquiétude, il est toujours possible d'utiliser Python avec les options -o et -oo. C'est la nomenclature qui change. En effet, utiliser Python avec -o ou -oo conduisait à la création de ces fichiers .pyo, indifférenciables du niveau d'optimisation, ce qui pouvait prêter à confusion.
Désormais nous avons:
python => .pyc
python -o => .opt-1.pyc
python -oo => .opt-2.pyc

PEP 0465 : un opérateur infixe dédié pour la multiplication matricielle

Python 3.5 voit l'apparition d'un nouvel opérateur, l'opérateur de la multiplication matricielle. Bien qu'en soit, cela soit une fonctionnalité qui semble importante, elle a été grandement sur-médiatisée. Cet opérateur, @ remplace la fonction de classe idoine sur les objets de type matrice, déjà développée et utilisée par d'autres bibliothèques (np.dot dans numpy par exemple).

S = (H.dot(beta) - r).T.dot(inv(H.dot(V).dot(H.T))).dot(H.dot(beta) - r)
# pourra s'écrire désormais
S = (H @ beta - r).T @ inv(H @ V @ H.T) @ (H @ beta - r)

La seconde forme est beaucoup plus lisible et proche de la notation mathématique.

En pratique, c'est inutile sans bibliothèque externe spécifique, puisqu'aucun objet ou type de la bibliothèque standard ne prend en compte cet opérateur. Il a été créé spécifiquement pour les bibliothèques de calcul numérique en Python, tel que numpy, pandas, blaze ou encore thenao.

PEP 492 : coroutines avec les mots-clés async et await

Ici, c'est la création de deux nouveaux mot-clés, async et await dont il est question. La programmation asynchrone n'ayant pas attendu Python 3.5, le nombre de bibliothèques externes dédiées, ainsi que le relatif regain d'intérêt pour ce type de programmation ont poussé une méthode standard dans le cœur du langage. En particulier, c'est l'intégration de la bibliothèque asyncio dont il est question.
De l'extérieur, async vient remplacer le décorateur asyncio.coroutine et await l'expression yield from.

La présentation du concept de générateur (dont les fonctions await et async sont parentes) et de la programmation asynchrone sont légèrement au-delà du but de cette dépêche. Mais voici un exemple illustrant le concept de programmation avec ces deux nouveaux mots-clés.

Exemple

import asyncio

async def echo_server():
    print('Serving on localhost:8000')
    await asyncio.start_server(handle_connection,
                               'localhost', 8000)

async def handle_connection(reader, writer):
    print('New connection...')

    while True:
        data = await reader.read(8192)

        if not data:
            break

        print('Sending {:.10}... back'.format(repr(data)))
        writer.write(data)

loop = asyncio.get_event_loop()
loop.run_until_complete(echo_server())
try:
    loop.run_forever()
finally:
    loop.close()

En vrac

  • Une nouvelle exception RecursionError est désormais levée lorsque la profondeur maximale de récursion est atteinte. Précédemment, nous avions droit à une RuntimeError.

Améliorations générales

Performance

  • collections.OrderedDict est maintenant implémenté en C, ce qui permet des gains d'un facteur 4 à 100.
  • functools.lru_cache() a été largement réécrit en C, permettant d'obtenir de meilleures performances (facteur 4 à 6)
  • de nombreuses opérations sur les adresses IP (comme subnets(), supernet(), summarize_address_range(), collapse_addresses(), …) ont subi une refonte avec des améliorations de performance allant d'un facteur de 3 à 15.
  • de nombreuses opérations sur io.BytesIO sont maintenant 1,5 à 2 fois plus rapides, via une réimplémentation des allocations mémoire similaires à StringIO.
  • la fonction marshal.dumps() peut-être jusqu'à 5 fois plus rapide dans le meilleur des cas. Sinon, l'amélioration se situe entre 20% et 80%.
  • l'encodeur UTF-32 est désormais entre 3 et 7 fois plus rapide.
  • les expressions régulières sont désormais traitées 10% plus rapidement.
  • instancier des fractions.Fraction est désormais 30% plus rapide.
  • les objets utilisés par le module random utilisent désormais deux fois moins de mémoire sur les compilations 64bits
  • les méthodes de l'objet String find(), rfind(), split(), partition() ainsi que les opérateurs sont désormais significativement plus rapides pour les recherches de sous-chaînes d'un caractère seulement.
  • json.dumps() a été optimisé de manière à ce que l'option ensure_ascii=False soit désormais aussi rapide que ensure_ascii=True

Sécurité

  • SSLv3 est maintenant désactivé, même s'il est possible de le réactiver en instanciant manuellement un ssl.SSLContext.
  • le module SSL a été retravaillé pour permettre de séparer la partie réseau de la gestion du protocole.
  • l'analyse des cookies HTTP est désormais plus simple et plus stricte, évitant d'éventuelles attaques par injection.

Petit changement important

  • subprocess.run() devient la fonction recommandée pour exécuter ses sous-processus.
  • le module traceback s'enrichit de deux nouvelles fonctions, walk_stack() et walk_tb(), ainsi que de trois nouvelles classes : TracebackException, StackSummary, and FrameSummary.
  • les fonctions getfullargspec(), getargvalues(), getcallargs(), getargvalues(), formatargspec() et formatargvalues() sont obsolètes. Il est recommandé d'utiliser l'API inspect.signature() en remplacement.
  • bool(datetime.time(0,0))==True (Précédement, cela retournait False)
  • ssl.SSLSocket.send() lève une exception plutôt que retourner 0 sur une socket non-bloquante si une opération bloque.
  • pour les noyaux supérieurs à 3.6, les sockets Python exportent désormais la fonctionnalité CAN_RAW_FD_FRAMES

L’avis de Guido

Le discours d'ouverture de Guido van Rossum pour l'EuroPython 2015 était intéressant à bien des égards. En voici les grandes lignes pour les curieux.

Il a ainsi tenu un discours sur la nécessité de passer à Python 3, tout simplement parce que c'est un meilleur langage, plus simple à apprendre (plus cohérent). De plus, il s'améliore avec le temps, là où Python 2.7 est un langage figé.

Pour ma part, cette évolution peut également être un frein pour de nombreuses équipes, puisqu'il y a régulièrement de la casse, ou même des régressions, là où Python 2.7 apporte une certaine stabilité.

Par ailleurs, il travaille chez DropBox, où ils utilisent une version de Python 2.7 largement modifiée. Certaines parties pourraient largement tirer bénéfices de l'utilisation de pypy, mais l'entreprise est très frileuse à l'idée des incompatibilités possibles & subtiles que cela pourrait engendrer, via des bugs complexes à reproduire et corriger.

C'est le problème principal des grosses bases de code, qu'il devient complexe de faire migrer après une masse critique de déploiements atteinte. Et c'est également le problème de Python 3.

Et pour finir, il explique un point noir, pour lui : tout ce qui tourne autour de la distribution de paquets pour Python. Il n'existe, selon lui, pas de solution miracle à ce problème.

  • # zip zip zip

    Posté par (page perso) . Évalué à 2. Dernière modification le 22/09/15 à 15:17.

    Ah oué, super donc, encore un nouveau format qui détourne zip avec une nouvelle extension comme ODT et sans mettre de magic devant… Donc ça va encore bien marcher dans les OS normaux qui utilisent un sniffer MIME au lieu de faire confiance aux extensions… :-(

    • [^] # Re: zip zip zip

      Posté par . Évalué à 1.

      Il a peut-être été utilisé un type MIME particulier pour les applis avec ces nouvelles extensions justement. La dépêche ne le mentionne pas.

      • [^] # Re: zip zip zip

        Posté par . Évalué à 3.

        Arrête-moi si je me trompe, mais si c'est un MIME spécifique, ça veut dire que ça n'est plus un MIME de fichier Zip, si? Auquel cas, on perd l'intérêt de pouvoir manipuler le fichier directement avec zip/unzip.

        • [^] # Re: zip zip zip

          Posté par . Évalué à 5. Dernière modification le 23/09/15 à 09:46.

          Je doute que (un)zip se limite à un type mime pour savoir s'il peut ou non décompresser le fichier. Il doit juste se contenter du format de fichier qu'on lui donne.

          Tu dois confondre avec la signature du fichier qui fait, elle, partie de la spécification du format de fichier. Le type mime est une chaine de caractère qu'on échange en parallèle du fichier pour identifier son type.

          Par contre, je pense que les navigateurs de fichiers contemporains peuvent très bien mémoriser l'action à effectuer en fonction de l'extension, et proposer des actions alternatives en fonction de la signature du fichier.

    • [^] # Re: zip zip zip

      Posté par . Évalué à 5.

      Je ne comprends pas la critique : c'est quoi cette histoire de "mettre un magic devant" ? Le but est justement que chacun puisse produire de tels fichiers de la même façon qu'on produit un fichier zip, sans outil supplémentaire.

      Quant aux "OS normaux", ils savent déjà reconnaître un fichier ODT à son extension, justement, je ne vois pas pourquoi ils ne pourraient pas aussi apprendre cette nouvelle extension.

      • [^] # Re: zip zip zip

        Posté par (page perso) . Évalué à 10. Dernière modification le 24/09/15 à 10:17.

        Certains systèmes ne se basent/basaient que sur l'extension, et on pouvait avoir des plantages ou des failles en cas d'extension fausse.
        Certains systèmes ne se basent/basaient que sur le magic, et on pouvait avoir des plantages ou des failles en cas de fichiers corrompus.
        Si le but est de fournir un traitement particulier à un type de fichiers (afficher une icône ou ouvrir avec telle application), il faut pouvoir différencier sur l'extension et/ou le magic. Si on ne sait pas déterminer rapidement le type de fichiers, on aura alors un traitement plus générique (une icône indifférenciée pour tous les zip par exemple, donc les .odt, les .pptx, les .jar, etc.). file sait différencier les 3 zip que sont un "OpenDocument Text", un "Microsoft PowerPoint 2007+" et un "Java archive data (JAR)" sans utiliser l'extension (via la libmagic, cf file-5.25/magic/Magdir/archive pour y trouver la gestion des anciens et actuels formats de {Star,Libre,Open,K}Office, des epub compressés, des archives "normales" et des autres formats compressés zip).
        Dans tous les cas ça ne dispense pas d'analyser correctement le fichier derrière pour éviter les surprises.

        • [^] # Re: zip zip zip

          Posté par . Évalué à 3.

          Certains systèmes ne se basent/basaient que sur l'extension, et on pouvait avoir des plantages ou des failles en cas d'extension fausse.
          Certains systèmes ne se basent/basaient que sur le magic, et on pouvait avoir des plantages ou des failles en cas de fichiers corrompus.

          Les plantages et les failles sont dus à des problèmes de qualité logicielle, pas à des problèmes d'extension ou de contenu du fichier. Un code qui traite des données de provenance inconnue doit être capable d'échouer proprement.

          file sait différencier les 3 zip que sont un "OpenDocument Text", un "Microsoft PowerPoint 2007+" et un "Java archive data (JAR)" sans utiliser l'extension (via la libmagic, cf file-5.25/magic/Magdir/archive pour y trouver la gestion des anciens et actuels formats de {Star,Libre,Open,K}Office, des epub compressés, des archives "normales" et des autres formats compressés zip).

          Je ne vois pas pourquoi on se retrouverait avec un JAR qui n'aurait pas l'extension ".jar", ou un ODT qui n'aurait pas l'extension ".odt". Pour moi, cela n'a rien de choquant qu'un tel fichier ne soit pas détecté correctement.

  • # Twisted

    Posté par (page perso) . Évalué à 6.

    Merci pour cette dépêche, je ne savais même pas qu'on pouvait exécuter une application complète depuis un zip.

    Est-ce que la PEP 461 ne va pas débloquer Twisted ? Il me semble que c'était un des points majeurs qui posait problème. Ils ont déjà porté plus de la moitié du code, et surtout trial est porté depuis peu sous Python 3, peut-on espérer voir enfin un port complet en 2016 ? J'espère surtout que toute la hiérarchie twisted.words va suivre rapidement.

    J'ai hâte !

    • [^] # Re: Twisted

      Posté par . Évalué à 3.

      Twisted travaille à son rythme, assez lent principalement parce que Python 3 n'est pas une priorité de ses développeurs. Honnêtement, vu l'existence de Tornado, d'asyncio et bien d'autres, je ne pense pas qu'on puisse dire que la PEP 461 était une condition nécessaire pour faire de la programmation réseau en Python 3.

      (d'ailleurs je t'encourage à essayer asyncio si tu veux faire de la programmation réseau en Python 3)

      • [^] # Re: Twisted

        Posté par (page perso) . Évalué à 3.

        Nécessaire peut-être pas, mais elle facilite le passage pour Twisted (il me semble avoir vu une longue discussion sur le sujet, mais je ne retrouve pas là).

        Je ne veux pas spécialement faire de la programmation réseau en Python 3, je veux porter mon projet en Python 3, et il est déjà entièrement basé sur Twisted. Je suis très content avec Twisted, c'est juste qu'on commence à avoir besoin de bosser en Python 3 (il y a des projets Python 3 qu'on veut utiliser, et côté Debian il est question de passer à Python 3 pour la prochaine version).

        Asyncio est très intéressant, et je m'y pencherai sérieusement quand on sera à Python 3, mais ce n'est pas encore comparable à Twisted, il n'y a pas que le côté asynchrone, y'a tout le framework qui va avec.

        • [^] # Re: Twisted

          Posté par (page perso) . Évalué à 3.

          Si tu es très content de Twisted, tant mieux.

          Par contre, pour avoir migré de Twisted vers AsyncIO il y a 1,5 an, je recommande ;-) A partir du moment que tu retrouve ta toolbox.

          Ce n'est pas encore aussi riche que Twisted, néanmoins, la couverture fonctionnelle est de + en + grande et la communauté est active.

          • [^] # Re: Twisted

            Posté par (page perso) . Évalué à 3.

            Oui j'ai vu qu'il y avait des choses qui se faisaient en XMPP, mais il va falloir encore un peu d'eau sous les ponts je pense. Ce qu'il y a, c'est qu'on a aussi une grosses base de code qu'on ne va pas pouvoir migrer comme ça, et que toute façon une migration devra se prévoir. Je n'exclus pas de passer un jour à Asyncio, ou au moins de l'utiliser en même temps.

  • # consistant --> cohérent

    Posté par . Évalué à 5.

    "Consistant" bien existe en français, mais permet de décrire… la consistance de quelque chose (à rapprocher de la viscosité, du volume, bref : une caractéristique physique), pas sa cohérence.

    • [^] # Re: consistant --> cohérent

      Posté par (page perso) . Évalué à 3.

      Corrigé, merci.

    • [^] # Re: consistant --> cohérent

      Posté par . Évalué à 0.

      "consistant" participe présent du verbe consister en plus d'être un adjectif.

      Larousse définition de consister : Comporter, être formé de.
      Dictionnaire de l'Académie Française CONSISTANT, ANTE, part. prés. et adj. CONSISTER, verbe trans.
      I.− Part. prés. de consister*.
      II.− Adj. Qui a de la consistance*.
      A.− DR., vx. [Avec un compl.] Qui consiste (en), qui se compose (de). Une terre consistante en prés, vignes, bois, labours.

      Même si c'est peu utilisé dans ce sens c'est tout à fait valable, c'est en plus le sens originel du terme. Et cela peut s'appliquer à n'importe quoi.

  • # PEP 484 : module typing, le nouveau standard pour les annotations de typage

    Posté par (page perso) . Évalué à 2.

    Au lieu d'un fichier séparé pour indiquer le type attendu d'une fonction, j'aurais trouvé ça bien plus pratique comme c'est fait dans Haskell, ce qui donnerait :

    upper_vowel :: str -> str
    def upper_vowel(words):
        blabla

    On aurait le type sur la ligne d'avant (c'est proche d'une annotation), sans rendre la définition de la fonction chiante à lire.

    M'enfin, c'est assez marrant ce module typing pour Pythong et son duck typing ¯\_(ツ)_/¯

    • [^] # Re: PEP 484 : module typing, le nouveau standard pour les annotations de typage

      Posté par (page perso) . Évalué à 3.

      ce n'est pas évident de faire ça en gardant un maximum de compatibilité.

      Personnellement, je me sers pas mal de ces annotations (ou en spécifiant le type dans les docstrings), mon IDE est tout à fait capable de les utiliser pour de la vérification de type. Je limite l'utilisation du typage dynamique de Python aux seuls cas où ça permet de vraiment diminuer la quantité de code. Au final, j'ai très peu de bugs à l'exécution (autres que des vraies erreurs d'algo que j'aurais eues avec n'importe quel langage). Un langage typé statiquement ne m'apporterait pas grand-chose à ce niveau-là, mais c'est fortement lié à l'IDE ET à la documentation.

      • [^] # Re: PEP 484 : module typing, le nouveau standard pour les annotations de typage

        Posté par . Évalué à 3. Dernière modification le 24/09/15 à 10:42.

        Je limite l'utilisation du typage dynamique de Python aux seuls cas où ça permet de vraiment diminuer la quantité de code.

        C'est un peu bizarre je trouve. Python a toujours était un grand défenseur du duck typing et je comprends tout à fait ce point de vu (on est pas obligé de faire des hiérarchies de classe pour avoir une méthode générique). Et je vois mal comment en tant que développeur d'une fonction tu peux savoir s'il est enviable de contraindre tes types d'entrée (par exemple pour permettre de passer des mocks/stubs pour les tests). Ce qui serait logique c'est de représenter les caractéristiques de l'objet (je veux en paramètre un objet qui a une méthode foo()), mais c'est bien trop complexe pour être utiliser (sans même parler de la mise en place), par exemple pour une méthode comme :

        def foo(a, b):
            if a % 2 == 0:
                b.bar()
            else
                b.bar2()

        Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

        • [^] # Re: PEP 484 : module typing, le nouveau standard pour les annotations de typage

          Posté par (page perso) . Évalué à 4.

          Ce qui serait logique c'est de représenter les caractéristiques de l'objet (je veux en paramètre un objet qui a une méthode foo()), mais c'est bien trop complexe pour être utiliser

          Bizarrement, c'est ce qu'Haskell fait aussi. Par exemple, pour tester a > 2, il te suffit de dire que a est un object ordonnable (typeclass) :

          (Ord a) => a -> return_type

          Bon, c'est pas forcément super lisible cette syntaxe, mais c'est ce dont tu parles.

          Je me demande de quoi Python s'inspire pour son module d'ailleurs…

          • [^] # Re: PEP 484 : module typing, le nouveau standard pour les annotations de typage

            Posté par . Évalué à 3.

            En effet, mais il est nécessaire d'avoir de l'inférence de type pour que ce soit utilisable sinon il faudrait recoder la totalité de ton code dans le système de type (pour gérer les combinatoires), bref ça demande à prouver ton programme :)

            Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

  • # 's/dépaquetage/déballage/' ?

    Posté par . Évalué à 1.

Suivre le flux des commentaires

Note : les commentaires appartiennent à ceux qui les ont postés. Nous n'en sommes pas responsables.