J'ai publié un article résumant le contenu des nouveautés de Python 3.5.
À partir de maintenant, le cycle de publication sera plus rapide, il semble donc que la fréquence de publication augmentera, mais je peux le faire en tant qu'ancien ingénieur boursier qui poursuit Python depuis 1.x Je veux juste continuer.
Et, comme je l'ai écrit dans cet article, Python2 a atteint la fin de vie le 1er janvier de cette année. J'ai hâte de voir quelles nouvelles fonctionnalités seront ajoutées à 3.9, qui sera publiée pour la première fois parmi les seuls Pythons qui ont Python 3 maintenu.
De plus, par rapport à la fois précédente, j'ai changé la façon de résumer par rapport à la fois précédente, par exemple "De petits changements sont écrits dans cet article, de grands changements sont écrits dans un autre article et un lien est fait ici", mais je voudrais également le suivre cette fois. Et au lieu de couvrir tous les changements, je me concentrerai sur ce qui m'intéresse personnellement.
Tout d'abord, la feuille de route de développement (PEP-596), qui est devenue un cycle d'un an à partir de ce moment.
2020.05.31
La première version bêta est sortie le 2020-05-19 presque comme prévu. Les nouvelles fonctionnalités de la version 3.9 sont maintenant terminées.
Ce qui suit a été ajouté aux "Modules nouvellement ajoutés".
Ce qui suit a été ajouté à "Amélioration du module".
TopologicalSorter
)gcd
, ajout de lcm
)Random.randbytes ()
)2020.05.04
La version alpha finale, a6, est sortie le 2020-04-28. Il est encore environ une semaine de retard.
Ce qui suit a été ajouté aux «Nouvelles fonctionnalités d'intérêt».
Ce qui suit a été ajouté à "Amélioration du module".
typing.Annotated
)2020.04.06
A4 est sorti le 2020-02-26 et a5 le 2020-03-23. C'est presque comme prévu avec un retard d'environ une semaine. Je pensais écrire de nouvelles fonctionnalités après la sortie de la version bêta, mais je l'ai mise à jour car elle était assez accumulée. Je ne les appellerai pas tous en même temps, alors je les ajouterai petit à petit.
2020.01.27
A3 est sorti le 2020-01-25. Pour autant que je sache, il ne semble pas y avoir de mise à jour majeure après le 1/18. Bogue GC (Garbage Collection)の修正が取り上げられていました。なおスケジュール的にa3は少し送れましたが、次のa4の予定は変わっていません。
2020.01.18
Première version. a2 est sorti le 2019-12-18, mais j'écris en fonction des nouveautés. Comme l'a3 était prévu pour le 2020-01-13, je pensais l'attendre, mais il semble qu'il soit tard, alors je vais le sortir pour le moment.
La période de support pour Python 2.7 a expiré et les anciennes fonctions compatibles qui ont été laissées seront coupées ou bientôt. Ils émettent des "DeprecatedWarning" depuis des années, mais il est possible qu'ils ne fonctionnent pas dès qu'ils sont mis à jour à moins qu'ils ne soient sérieusement vérifiés.
Pour vérifier, vous pouvez soit émettre un message d'avertissement comme -W default
au moment de l'exécution, soit sauter le pas et faire une erreur avec -W error
.
→ Article séparé: Nouvelles fonctionnalités de Python 3.9 (1) - L'opérateur d'ensemble de somme peut être utilisé dans le type dictionnaire
Les méthodes «removeprefix (prefix)» et «removesuffix (suffix)» ont été ajoutées à «str», «bytes», «bytearray» et «collections.UserString». Il s'agit d'une méthode qui coupe les sous-chaînes au début et à la fin d'une chaîne (ou d'une chaîne d'octets). Par exemple
>>> 'test_sample.txt'.removeprefix('test_')
'sample.txt'
>>> 'abc.doc'.removesuffix('.doc')
'abc'
Vous pouvez faire quelque chose comme ça. Je me demande: "Hein? N'y avait-il pas une telle méthode?", Mais ce n'était pas le cas. En fait, il existe des méthodes similaires telles que «lstrip» et «rstrip». Normalement
>>> ' spacey_head'.lstrip()
'spacey_head'
>>> 'spacey_tail '.rstrip()
'spacey_tail'
Il est utilisé pour effacer les caractères vides sous la forme de, mais quand un argument est donné à cela, il a une spécification étrange (?) Qui "supprime jusqu'à ce qu'il ne corresponde à aucun des caractères contenus dans la chaîne de caractères". Il est facile de faire des erreurs. Par exemple, essayez de faire la même chose que l'exemple ci-dessus
>>> 'abc.doc'.rstrip('.doc')
'ab'
>>> 'test_sample.txt'.lstrip('test_')
'ample.txt'
Ensuite, il disparaît dans un endroit inattendu et vous pourriez être surpris. En fait, ce comportement déroute les utilisateurs de Python, ce qui est l'une des raisons de l'ajout de nouvelles méthodes pour supprimer les préfixes et les suffixes.
Dans le passé, lorsque vous vouliez taper-annoter un type de collection tel qu'une liste ou un taple, vous utilisiez le module typing
List ou
Tuple` pour ce faire.
import typing
def greet_all(names: typing.List[str]) -> None:
for name in names:
print("hello", name)
Beaucoup de gens aimeraient utiliser les noms de type «list» et «tuple» tels quels, tout comme «str» et «int ». Cela sera réalisé en 3.9. En d'autres termes
def greet_all(names: list[str]) -> None:
for name in names:
print("hello", name)
Vous pourrez écrire!
La partie qui lit et analyse le code dans le système de traitement du langage s'appelle un analyseur, mais jusqu'à présent, Python utilisait un type d'analyseur appelé LL (1). Il s'agit d'un analyseur qui effectue une analyse de syntaxe descendante avec une seule analyse prospective, et est souvent utilisé dans l'analyse du langage de programmation avec le type ascendant appelé type LR. Bien qu'une analyse efficace soit possible, il y a le problème que la grammaire qui peut être traitée est limitée. Il existe déjà une syntaxe que LL (1) ne peut pas gérer en Python, donc une logique spéciale est intégrée en tant que post-traitement de l'analyse parseur. Cette fois, nous allons introduire un nouvel analyseur PEG afin que l'analyseur seul puisse gérer différentes syntaxes.
Par exemple, si vous souhaitez lier plusieurs variables avec l'instruction with
with (
open("a_really_long_foo") as foo,
open("a_really_long_baz") as baz,
open("a_really_long_bar") as bar
):
...
Je veux l'écrire comme ça, mais cela ne peut pas être géré par l'analyseur actuel. Je veux introduire un nouvel analyseur pour gérer ce genre de chose.
Python 3.9 possède également un analyseur LL (1) traditionnel. La valeur par défaut utilise le nouvel analyseur, mais vous pouvez également appeler l'ancien avec l'option d'invocation (-X oldparser
) ou la variable d'environnement ( PYTHONOLDPARSER = 1
). Cependant, il s'agit d'une mesure transitoire, et en ce qui concerne Python 3.10, l'ancien analyseur sera retiré et seulement le nouveau. Et les spécifications linguistiques sont basées sur cela.
au lieu de
ValueError`Dans un package qui a une structure hiérarchique, les modules de la hiérarchie supérieure
import ..module_1
Vous pouvez l'importer comme ceci, mais si vous faites cela au niveau supérieur du package, par exemple, vous obtiendrez une erreur. Dans ce cas, jusqu'à maintenant
ValueError: attempted relative import beyond top-level package
J'ai eu une erreur de valeur, mais à partir de 3,9
ImportError: attempted relative import beyond top-level package
Cela devient «Erreur d'importation». De même, l'erreur dans ʻimportlib.util.resove_name () va de
ValueError à ʻImportError
. C'est un changement incompatible, donc le code qui intercepte et gère cette exception doit être changé, mais c'est un changement légitime.
Lorsque vous utilisez python script.py
, le nom de fichier du script exécuté sera entré dans l'attribut __file__
. Je vais. ~~ De plus, Quoi de neuf dit que la valeur de sys.path [0]
est aussi un chemin absolu, mais c'est aussi le cas avec la version actuelle, donc je pense que c'est une erreur dans le document. Je suis en train de penser. ~~ -> Ceci a été corrigé en listant un rapport de bogue.
Ensuite, suite aux discussions du passé, il semble que sys.argv [0]
essayait également de changer en chemin absolu. Cependant, il y avait un tsukkomi disant que la gamme d'influence était trop large et il semble qu'elle a été annulée. Je suis content de penser que c'est un peu exagéré. Huh.
replace
pour les chaînes vides (" ")Le comportement lors de l'application de la méthode replace
à une chaîne de caractères vide (" ") change. Auparavant, l'argument optionnel count
(qui spécifie le nombre de changements à appliquer) donnait des résultats étranges.
"".replace("", "p") = "p"
"".replace("", "p", 1) = ""
"".replace("", "p", 2) = ""
Lorsqu'il atteint 3,9, il devient plus cohérent.
"".replace("", "p") = "p"
"".replace("", "p", 1) = "p"
"".replace("", "p", 2) = "p"
Eh bien, pour être clair, je pense que c'est un niveau de correction de bogue, mais "(je ne pense pas que ce soit possible) je ne veux pas revenir en arrière vers la version précédente car ce serait un problème pour les personnes qui implémentent ce comportement." chose.
zoneinfo
Un nouveau module zone info
a été ajouté à la bibliothèque standard. Il fournit les fonctionnalités de la base de données de fuseaux horaires de l'IANA en standard. Certaines des fonctions fournies par le module datetime
prennent les informations de fuseau horaire comme argument, mais la classe standard timezone
fournit des fonctionnalités minimales et essaie de faire quelque chose d'un peu élaboré. Ensuite, j'ai dû me fier à une bibliothèque externe telle que python-dateutil. C'est beaucoup plus facile avec le nouveau module zoneinfo
ajouté en 3.9.
Par exemple.
>>> from zoneinfo import ZoneInfo
>>> from datetime import datetime
>>> tzinfo = ZoneInfo("Europe/Brussels")
>>> dt = datetime(2020, 10, 24, 12, tzinfo=tzinfo)
>>> print(dt)
2020-10-24 12:00:00+02:00
>>> dt.tzname()
'CEST'
>>> dt = datetime(2020, 10, 25, 12, tzinfo=tzinfo)
>>> print(dt)
2020-10-25 12:00:00+01:00
>>> dt.tzname()
'CET'
De nombreux pays d'Europe occidentale ont adopté «l'heure d'Europe centrale». Les pays de ce fuseau horaire ont l'heure d'été du dernier dimanche de mars au dernier dimanche d'octobre, mais si vous utilisez zoneinfo
, il n'y a pas de problème à partir des informations de localisation uniquement sans connaître le moment de commutation. Vous pouvez voir qu'il peut gérer les fuseaux horaires.
asyncio
Il y a quelques changements dans ʻasyncio`.
Ce que j'ai trouvé le plus intéressant, c'est l'ajout de PidfdChildWatcher
. Il est possible de créer plusieurs processus enfants dans ʻasyncio` et d'attendre le résultat de manière asynchrone, mais il est étonnamment difficile de "détecter la fin du processus enfant". Jusqu'à présent, environ 4 méthodes ont été implémentées, une méthode est de créer un thread pour surveiller chaque fois qu'un processus enfant est créé, deux méthodes utilisent un signal (SIGCHLD) et ʻos.waitpid () ʻest utilisé. Il y avait un moyen. Chacun a ses avantages et ses inconvénients et peut être modifié par l'utilisateur selon les besoins (la valeur par défaut est threadée). Cette fois, celui qui utilise pidfs est ajouté ici.
C'est la première fois que j'apprends les pidfs, mais avec un nouveau périphérique introduit sous Linux, il sera possible de pointer des processus avec des descripteurs de fichiers. Sous Unix, les processus sont généralement pointés par PID (ID de processus), mais comme ils sont partagés dans tout le système et sont des entiers signés 32 bits, ils finiront par être épuisés si le système continue de s'exécuter et que les processus sont créés et supprimés à plusieurs reprises. Je le ferai. Cela se traduit par la réutilisation des PID précédemment utilisés (des processus qui ont déjà disparu), qui, nous le savons, peuvent être une faille de sécurité. En guise de contre-mesure, l'idée d'un descripteur de fichier qui attribue un numéro individuel à chaque processus est appliquée au processus et l'accès au processus enfant peut être effectué en l'utilisant.
Le PidfdChildWatcher
ajouté dans 3.9 ne nécessite pas de threads ou de signaux et n'interfère pas avec d'autres processus, ce qui en fait une implémentation de surveillance de processus enfant" juste ". Le problème est qu'il ne peut être utilisé qu'avec des versions relativement nouvelles de Linux (5.3 et plus), mais je pense que s'il se propage progressivement, il y aura plus d'opportunités de l'utiliser.
datetime
datetime.isocalendar ()
et date.isocalendar ()
utilisé pour renvoyer le nplet(année, semaine, jour de la semaine)
comme suit:
>>> from datetime import datetime
>>> dt = datetime(2020,5,30)
>>> isocal = dt.isocalendar()
>>> isocal
(2020, 22, 6)
>>> isocal[0]
2020
Avec les tapples, c'est difficile à comprendre car il faut utiliser un index numérique pour accéder aux informations qu'il contient. Cela renverra les taples nommés de 3.9.
>>> from datetime import datetime
>>> dt = datetime(2020,5,30)
>>> isocal = dt.isocalendar()
>>> isocal
datetime.IsoCalendarDate(year=2020, week=22, weekday=6)
>>> isocal.year
2020
C'est beaucoup plus facile car vous pouvez y accéder comme un attribut d'objet.
functools
Une fonction de tri des graphes dirigés appelée TopologicalSorter
a été fournie en tant que classe. Cela a été traité dans un article séparé dans Quoi de neuf en Python 3.9 (2) - Tri des graphes non-circuit dirigés en Python.
hashlib
En tant qu'option lors de la compilation des systèmes de traitement Python, il est désormais possible de désactiver (sélectivement) l'implémentation de la fonction de hachage intégrée. Il sert à imposer l'utilisation de l'implémentation OpenSSL.
ipaddress
L'adresse de portée définie dans la RFC4007 peut être spécifiée sous la forme «<ipv6_address>% scope_id». De plus, un attribut appelé scope_id
a été ajouté à la classe ʻIPv6Address`, et vous pouvez y vérifier la valeur des adresses étendues.
math
Gcd
, qui calcule l'engagement maximum, peut désormais prendre 3 arguments ou plus. Auparavant, il était limité à deux. De plus, «lcm» a été ajouté pour calculer le multiple commun minimum. Cela prend en charge 3 arguments ou plus depuis le début.
>>> import math
>>> math.gcd(120, 156, 180)
12
>>> math.lcm(120, 156, 180)
4680
os
pidfd_open ()
et P_PIDFD
ont été ajoutés. Cela fait partie du support des pidfs dont nous avons parlé dans ʻasyncio` ci-dessus.
pathlib
Pathlib.Path.readlink ()
a été ajouté pour suivre le lien symbolique. Par exemple, si vous avez un lien appelé b-> a
, vous pouvez toujours utiliser ʻos.readlink ()`
>>> import os
>>> os.readlink('b')
'a'
Mais j'ai dû donner le chemin du fichier sous forme de chaîne. Depuis 3.9, readlink ()
a été ajouté en tant que méthode à l'objet Path
, donc
>>> from pathlib import Path
>>> p = Path('b')
>>> p.readlink()
PosixPath('a')
Vous pouvez le faire comme ça. Dans cet exemple, il y a plus d'étapes que ʻos.readlink () , mais un outil qui utilise un objet Path pour afficher des liens symboliques sous
/ usr / local / bin`, par exemple, ressemble à ceci Peut écrire.
from pathlib import Path
p = Path('/usr/local/bin/')
for child in p.iterdir():
if child.is_symlink():
print(f'{child} -> {child.readlink()}')
random
Ajout de Random.randbytes ()
, qui renvoie des nombres aléatoires en octets de longueur arbitraire. Cependant, comme le nombre aléatoire généré par le module aléatoire est un nombre pseudo aléatoire, il est bon pour la modélisation et la simulation, mais il n'est pas recommandé pour les applications de sécurité et le chiffrement. Une fonction appelée secrets.token_bytes ()
est déjà fournie à ces fins.
typing
Une classe appelée ʻAnnotated a été ajoutée au module
typing` pour vous permettre d'ajouter des métadonnées pour taper des informations d'indication.
Par exemple, supposons qu'une variable membre appelée value dans une classe appelée ʻIntInRange soit de type integer (ʻint
) et a une valeur comprise entre -10 et 5. Dans le passé, des informations de type indiquant qu'il s'agissait d'un type entier étaient ajoutées, mais il n'était pas possible de spécifier une plage de nombres. À partir de 3.9, vous pouvez mettre des données arbitraires dans le deuxième argument et les suivants de ʻAnnotated` comme indiqué ci-dessous, j'ai donc essayé de spécifier la plage de valeurs numériques avec un taple.
Et les informations d'indication peuvent être récupérées en passant True à l'argument ʻinclude_extras ajouté de 3.9 à la fonction
get_type_hints`. Si vous créez un vérificateur de type spécial à l'aide de cela, vous pouvez vérifier le type, y compris la plage de valeurs.
from typing import Annotated, get_type_hints
class IntInRange:
value: Annotated[int, (-10, 5)]
get_type_hints(IntInRange) == {'value': int}
get_type_hints(IntInRange, include_extras=True) == {'value': Annotated[int, (-10, 5)]}
math.factorial ()
insère une virgule flottante, un avertissement indiquant qu'il sera obsolète apparaîtra même s'il est 0 après la virgule décimale. Il semble que ce soit "TypeError" dans le futur.
--Dans le module random
, tout type de données peut maintenant être utilisé comme une graine tant qu'elle peut être hachée, mais pour s'assurer que le résultat est unique, None
, ʻint,
float, Seuls
str,
bytes et bytearray` peuvent être amorcés et utilisés.tostring ()
et fromstring ()
de ʻarray.arrayont été supprimées. Il est obsolète depuis environ 3.2 et est devenu un alias pour
tobytes ()et
frombytes ()`.Voici un résumé des modifications apportées à Python 3.9. Puisque la version 3.9 est également en version bêta, je pense que cet article est presque complet, mais il y a des parties d'optimisation et des parties qui n'ont pas encore été écrites, je les ajouterai donc si nécessaire.
Recommended Posts