Ich habe einen Artikel veröffentlicht, der den Inhalt von Neuigkeiten aus Python 3.5 zusammenfasst.
Von nun an wird der Veröffentlichungszyklus schneller sein, so dass es den Anschein hat, dass die Häufigkeit der Veröffentlichung zunimmt, aber ich kann es als alter Aktieningenieur tun, der Python seit 1.x verfolgt. Ich möchte einfach weitermachen.
Und wie ich in diesem Artikel geschrieben habe, hat Python2 am 1. Januar dieses Jahres das Ende seiner Lebensdauer erreicht. Ich freue mich darauf zu sehen, welche neuen Funktionen zu 3.9 hinzugefügt werden, das zum ersten Mal unter den einzigen Pythons veröffentlicht wird, die Python 3 beibehalten haben.
Darüber hinaus habe ich gegenüber der vorherigen Zeit die Art der Zusammenfassung gegenüber der vorherigen Zeit geändert, z. B. "Kleine Änderungen werden in diesem Artikel geschrieben, große Änderungen werden in einem anderen Artikel geschrieben und hier wird ein Link erstellt", aber ich möchte dies auch dieses Mal verfolgen. Und anstatt alle Änderungen abzudecken, werde ich mich auf das konzentrieren, was mir persönlich wichtig ist.
Zunächst die Entwicklungs-Roadmap (PEP-596), die ab diesem Zeitpunkt zu einem einjährigen Zyklus geworden ist.
2020.05.31
Die erste Beta wurde am 2020-05-19 fast wie geplant veröffentlicht. Jetzt sind die neuen Funktionen in 3.9 abgeschlossen.
Folgendes wurde zu "Neu hinzugefügte Module" hinzugefügt.
Folgendes wurde zu "Verbesserung des Moduls" hinzugefügt.
isocalendar ()
)TopologicalSorter
)gcd
, Hinzufügung von lcm
)os.pidfd_open ()
und os.P_PIDFD
)Random.randbytes ()
)2020.05.04
Die endgültige Alpha-Version a6 wurde am 28.04.2020 veröffentlicht. Es ist immer noch ungefähr eine Woche zu spät.
Folgendes wurde zu "Neue interessante Funktionen" hinzugefügt.
Folgendes wurde zu "Verbesserung des Moduls" hinzugefügt.
2020.04.06
A4 wurde am 26.02.2020 und a5 am 23.03.2020 veröffentlicht. Es ist fast wie geplant mit einer Verzögerung von etwa einer Woche. Ich habe darüber nachgedacht, neue Funktionen zu schreiben, nachdem die Beta veröffentlicht wurde, aber ich habe sie aktualisiert, weil sie ziemlich angesammelt war. Ich werde sie nicht alle auf einmal anrufen, also werde ich sie nach und nach hinzufügen.
2020.01.27
A3 wurde am 25.01.2020 veröffentlicht. Soweit ich sehen kann, scheint es nach dem 18. Januar kein größeres Update zu geben. GC (Garbage Collection) Bugの修正が取り上げられていました。なおスケジュール的にa3は少し送れましたが、次のa4の予定は変わっていません。
2020.01.18
Erste Version. a2 wurde am 18.12.2019 veröffentlicht, aber ich schreibe basierend auf den Neuerungen. Da a3 für 2020-01-13 geplant war, dachte ich, ich würde darauf warten, aber es scheint, dass es spät ist, also werde ich es vorerst löschen.
Die Unterstützungsfrist für Python 2.7 ist abgelaufen, und die in der Vergangenheit verbleibenden kompatiblen Funktionen werden abgeschnitten oder bald. Sie geben seit Jahren "DeprecatedWarning" heraus, aber es ist möglich, dass sie nicht funktionieren, sobald sie aktualisiert werden, es sei denn, sie werden ernsthaft überprüft. Zur Überprüfung können Sie entweder zur Laufzeit eine Warnmeldung als "-W default" ausgeben oder den Sprung wagen und mit "-W error" einen Fehler machen.
→ Separater Artikel: Neue Funktionen von Python 3.9 (1) - Der Summensatzoperator kann im Wörterbuchtyp verwendet werden
Die Methoden "removeprefix (Präfix)" und "removeesuffix (Suffix)" wurden zu "str", "bytes", "bytearray" und "collection.UserString" hinzugefügt. Dies ist eine Methode, die die Teilzeichenfolgen am Anfang und Ende einer Zeichenfolge (oder Byte-Zeichenfolge) abschneidet. Zum Beispiel
>>> 'test_sample.txt'.removeprefix('test_')
'sample.txt'
>>> 'abc.doc'.removesuffix('.doc')
'abc'
Sie können so etwas tun. Ich frage mich: "Huh? Gab es nicht eine solche Methode?", Aber es war nicht so. Tatsächlich gibt es ähnliche Methoden wie "lstrip" und "rstrip". Normalerweise
>>> ' spacey_head'.lstrip()
'spacey_head'
>>> 'spacey_tail '.rstrip()
'spacey_tail'
Es wird verwendet, um leere Zeichen in Form von zu löschen, aber wenn ein Argument dafür angegeben wird, hat es eine seltsame (?) Spezifikation, die "löscht, bis es nicht mehr mit einem der in der Zeichenfolge enthaltenen Zeichen übereinstimmt". Es ist leicht, Fehler zu machen. Versuchen Sie beispielsweise, dasselbe wie im obigen Beispiel zu tun
>>> 'abc.doc'.rstrip('.doc')
'ab'
>>> 'test_sample.txt'.lstrip('test_')
'ample.txt'
Dann verschwindet es an einem unerwarteten Ort und Sie können überrascht sein. Tatsächlich verwirrt dieses Verhalten Python-Benutzer. Dies ist einer der Gründe für das Hinzufügen neuer Methoden zum Entfernen von Präfixen und Suffixen.
Wenn Sie bisher Anmerkungen mit einem Sammlungstyp wie einer Liste oder einem Taple eingeben möchten, haben Sie dazu das "Typing" -Modul "List" oder "Tuple" verwendet.
import typing
def greet_all(names: typing.List[str]) -> None:
for name in names:
print("hello", name)
Viele Leute möchten die Typnamen "list" und "tuple" so verwenden, wie sie sind, genau wie "str" und "int". Dies wird in 3.9 erreicht. Mit anderen Worten
def greet_all(names: list[str]) -> None:
for name in names:
print("hello", name)
Sie können schreiben!
Der Teil, der den Code im Sprachverarbeitungssystem liest und analysiert, wird als Parser bezeichnet. Bisher verwendete Python jedoch einen Parsertyp namens LL (1). Dies ist ein Parser, der eine Top-Down-Syntaxanalyse mit nur einem Blick nach vorne durchführt und häufig in der Programmiersprachenanalyse zusammen mit dem Bottom-Up-Typ LR verwendet wird. Während eine effiziente Analyse möglich ist, besteht das Problem, dass die Grammatik, die gehandhabt werden kann, begrenzt ist. Es gibt bereits eine Syntax, die LL (1) in Python nicht verarbeiten kann. Daher ist eine spezielle Logik als Nachbearbeitung der Parser-Analyse integriert. Dieses Mal werden wir einen neuen PEG-Parser einführen, damit der Parser allein verschiedene Syntaxen verarbeiten kann.
Zum Beispiel, wenn Sie mehrere Variablen mit der with-Anweisung binden möchten
with (
open("a_really_long_foo") as foo,
open("a_really_long_baz") as baz,
open("a_really_long_bar") as bar
):
...
Ich möchte es so schreiben, aber dies kann vom aktuellen Parser nicht verarbeitet werden. Ich möchte einen neuen Parser einführen, um so etwas zu handhaben.
Python 3.9 hat auch einen traditionellen LL (1) -Parser. Der Standard verwendet den neuen Parser, aber Sie können den alten auch mit der Aufrufoption (-X oldparser
) oder der Umgebungsvariablen ( PYTHONOLDPARSER = 1
) aufrufen. Dies ist jedoch eine Übergangsmaßnahme, und wenn es um Python 3.10 geht, wird der alte Parser zurückgezogen und nur der neue. Und die Sprachspezifikationen basieren darauf.
In einem Paket mit hierarchischer Struktur befinden sich die Module in der oberen Hierarchie
import ..module_1
Sie können es so importieren, aber wenn Sie dies beispielsweise auf der obersten Ebene des Pakets tun, wird eine Fehlermeldung angezeigt. In diesem Fall bis jetzt
ValueError: attempted relative import beyond top-level package
Ich habe einen "Wertefehler", aber ab 3.9
ImportError: attempted relative import beyond top-level package
Es wird zu "ImportError". Ebenso geht der Fehler in "importlib.util.resove_name ()" von "ValueError" zu "ImportError". Da es sich um eine inkompatible Änderung handelt, muss der Code, der diese Ausnahme abfängt und behandelt, geändert werden. Dies ist jedoch eine legitime Änderung.
Wenn Sie python script.py
ausführen, wird der Dateiname des ausgeführten Skripts in das Attribut __file__
eingegeben, aber bisher war es ein relativer Pfad, wie er in der Befehlszeile geschrieben wurde, aber ab 3.9 ist er ein absoluter Pfad Ich werde. ~~ Außerdem heißt es in "Was ist neu", dass der Wert von "sys.path [0]" ebenfalls ein absoluter Pfad ist. Dies ist jedoch auch bei der aktuellen Version der Fall, sodass ich denke, dass dies ein Fehler im Dokument ist. Ich denke. ~~ -> Dies wurde durch Auflisten eines Fehlerberichts behoben.
Dann, nach den Diskussionen in der Vergangenheit, scheint es, dass sys.argv [0]
auch versucht hat, zu einem absoluten Pfad zu wechseln. Es gab jedoch einen Tsukkomi, der sagte, dass der Einflussbereich zu groß sei, und es scheint, dass er aufgehoben wurde. Ich bin froh, dass ich denke, dass es ein wenig übertrieben ist. Huh.
Das Verhalten beim Anwenden der Ersetzungsmethode auf eine leere Zeichenfolge ("") ändert sich. Zuvor lieferte das optionale Argument "count" (das angibt, wie viele Änderungen angewendet werden sollen) seltsame Ergebnisse.
"".replace("", "p") = "p"
"".replace("", "p", 1) = ""
"".replace("", "p", 2) = ""
Wenn es 3,9 erreicht, wird es konsistenter.
"".replace("", "p") = "p"
"".replace("", "p", 1) = "p"
"".replace("", "p", 2) = "p"
Um klar zu sein, ich denke, es liegt auf der Ebene der Fehlerkorrekturen, aber "(ich denke nicht, dass es möglich ist) Ich möchte nicht auf die vorherige Version zurückportieren, da dies ein Problem für Leute wäre, die dieses Verhalten implementieren." Ding.
zoneinfo
Der Standardbibliothek wurde ein neues "Zoneninfo" -Modul hinzugefügt. Es bietet standardmäßig die Funktionalität der IANA-Zeitzonendatenbank. Einige der vom Modul "datetime" bereitgestellten Funktionen verwenden Zeitzoneninformationen als Argument, aber die Standardklasse "timezone" bietet nur minimale Funktionen und versucht, etwas Aufwändiges zu tun. Dann musste ich mich auf eine externe Bibliothek wie python-dateutil verlassen. Dies ist viel einfacher mit dem neuen "zoneinfo" -Modul, das in 3.9 hinzugefügt wurde.
Zum Beispiel.
>>> 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'
Viele westeuropäische Länder haben die "Mitteleuropäische Zeit" eingeführt. Länder in dieser Zeitzone haben Sommerzeit vom letzten Sonntag im März bis zum letzten Sonntag im Oktober. Wenn Sie jedoch "zoneinfo" verwenden, gibt es kein Problem nur mit den Standortinformationen, ohne den Schaltzeitpunkt zu kennen. Sie können sehen, dass es Zeitzonen verarbeiten kann.
asyncio
Es gibt einige Änderungen an "asyncio".
Am interessantesten fand ich die Hinzufügung von PidfdChildWatcher
. Es ist möglich, mehrere untergeordnete Prozesse in "asyncio" zu erstellen und asynchron auf das Ergebnis zu warten, aber es ist überraschend schwierig, "die Beendigung des untergeordneten Prozesses zu erkennen". Bisher wurden ungefähr 4 Methoden implementiert, eine Methode besteht darin, bei jeder Erstellung eines untergeordneten Prozesses einen Thread zur Überwachung zu erstellen, zwei Methoden verwenden ein Signal (SIGCHLD) und "os.waitpid ()" wird verwendet. Es gab einen Weg. Jedes hat seine Vor- und Nachteile und kann vom Benutzer nach Bedarf geändert werden (Standard ist Threaded). Dieses Mal wird hier die mit pidfs hinzugefügt.
Diesmal habe ich auch zum ersten Mal etwas über pidfs gelernt, aber mit einem neuen Mechanismus, der in Linux eingeführt wurde, wird es möglich sein, Prozesse mit Dateideskriptoren zu verweisen. Unter Unix wird auf Prozesse normalerweise durch die PID (Prozess-ID) verwiesen. Da sie jedoch im gesamten System gemeinsam genutzt werden und Ganzzahlen mit 32-Bit-Vorzeichen sind, sind sie möglicherweise erschöpft, wenn das System weiterhin ausgeführt wird und Prozesse wiederholt erstellt und gelöscht werden. Ich werde das machen. Dies führt zur Wiederverwendung zuvor verwendeter PIDs (von Prozessen, die bereits verschwunden sind), von denen wir wissen, dass sie eine Sicherheitslücke darstellen können. Als Gegenmaßnahme wird die Idee eines Dateideskriptors, der jedem Prozess eine individuelle Nummer zuweist, auf den Prozess angewendet, und der Zugriff auf den untergeordneten Prozess kann damit durchgeführt werden.
Der in 3.9 hinzugefügte PidfdChildWatcher erfordert keine Threads oder Signale und stört andere Prozesse nicht. Dies macht ihn zu einer "genau richtigen" Implementierung zur Überwachung untergeordneter Prozesse. Das Problem ist, dass es nur mit relativ neuen Linux-Versionen (5.3 und höher) verwendet werden kann, aber ich denke, wenn es sich allmählich ausbreitet, wird es mehr Möglichkeiten geben, es zu verwenden.
datetime
datetime.isocalendar ()
und date.isocalendar ()
werden verwendet, um das (Jahr, Woche, Wochentag)
Tupel wie folgt zurückzugeben:
>>> from datetime import datetime
>>> dt = datetime(2020,5,30)
>>> isocal = dt.isocalendar()
>>> isocal
(2020, 22, 6)
>>> isocal[0]
2020
Es ist schwer zu verstehen, ob es sich um ein Taple handelt, da Sie einen numerischen Index verwenden müssen, um auf die darin enthaltenen Informationen zuzugreifen. Dies gibt benannte Taples ab 3.9 zurück.
>>> from datetime import datetime
>>> dt = datetime(2020,5,30)
>>> isocal = dt.isocalendar()
>>> isocal
datetime.IsoCalendarDate(year=2020, week=22, weekday=6)
>>> isocal.year
2020
Es ist viel einfacher, weil Sie wie ein Objektattribut darauf zugreifen können.
functools
Als Klasse wurde eine Funktion zum Sortieren gerichteter Graphen mit dem Namen "TopologicalSorter" bereitgestellt. Dies wurde in einem separaten Artikel in Was ist neu in Python 3.9 (2) - Sortieren von gerichteten Nicht-Schaltungsgraphen in Python behandelt.
hashlib
Es ist jetzt möglich (selektiv), die integrierte Implementierung der Hash-Funktion als Option beim Kompilieren des Python-Prozesses zu deaktivieren. Es dient zur Durchsetzung der Verwendung der OpenSSL-Implementierung.
ipaddress
Die in RFC4007 definierte Bereichsadresse kann in Form von "<ipv6_address>% scope_id" angegeben werden. Außerdem wurde der Klasse "IPv6Address" ein Attribut mit dem Namen "scope_id" hinzugefügt, und Sie können den Wert dort auf Adressen mit Gültigkeitsbereich überprüfen.
math
Gcd
, das die maximale Verpflichtung berechnet, kann jetzt 3 oder mehr Argumente annehmen. Zuvor war es auf zwei beschränkt. Außerdem wurde "lcm" hinzugefügt, um das minimale gemeinsame Vielfache zu berechnen. Dies unterstützt von Anfang an 3 oder mehr Argumente.
>>> import math
>>> math.gcd(120, 156, 180)
12
>>> math.lcm(120, 156, 180)
4680
os
pidfd_open () und P_PIDFD wurden hinzugefügt. Dies ist Teil der Unterstützung für PIDFS, über die wir oben in "asyncio" gesprochen haben.
pathlib
Pathlib.Path.readlink ()
wurde hinzugefügt, um dem symbolischen Link zu folgen. Wenn Sie beispielsweise einen Link namens "b-> a" haben, können Sie weiterhin "os.readlink ()" verwenden
>>> import os
>>> os.readlink('b')
'a'
Aber ich musste den Dateipfad als String angeben. Seit 3.9 wurde "readlink ()" als Methode zum "Path" -Objekt hinzugefügt
>>> from pathlib import Path
>>> p = Path('b')
>>> p.readlink()
PosixPath('a')
Sie können es so machen. In diesem Beispiel ist die Anzahl der Schritte größer als "os.readlink ()", aber ein Tool, das ein Path-Objekt verwendet, um symbolische Links unter "/ usr / local / bin" anzuzeigen, sieht beispielsweise so aus. Kann schreiben.
from pathlib import Path
p = Path('/usr/local/bin/')
for child in p.iterdir():
if child.is_symlink():
print(f'{child} -> {child.readlink()}')
random
Random.randbytes ()
hinzugefügt, das Zufallszahlen in Bytes beliebiger Länge zurückgibt. Da es sich bei der vom Zufallsmodul generierten Zufallszahl um eine Pseudozufallszahl handelt, eignet sie sich für die Modellierung und Simulation, wird jedoch für Sicherheitsanwendungen und die Verschlüsselung nicht empfohlen. Für solche Zwecke ist bereits eine Funktion namens "secret.token_bytes ()" vorgesehen.
typing
Dem Modul "Typing" wurde eine Klasse mit dem Namen "Annotated" hinzugefügt, mit der Sie Metadaten zum Eingeben von Hinweisinformationen hinzufügen können.
Angenommen, eine Mitgliedsvariable mit dem Namen value in einer Klasse mit dem Namen IntInRange ist vom Typ Integer (int) und hat einen Wert im Bereich von -10 bis 5. In der Vergangenheit wurden Typinformationen hinzugefügt, dass es sich um einen Ganzzahltyp handelt, es war jedoch nicht möglich, einen Zahlenbereich anzugeben. Ab 3.9 können Sie beliebige Daten in das zweite und die nachfolgenden Argumente von "Annotated" einfügen, wie unten gezeigt. Daher habe ich versucht, den Bereich der numerischen Werte mit einem Taple anzugeben.
Und die Hinweisinformationen können abgerufen werden, indem True an das Argument include_extras
übergeben wird, das von 3.9 zur Funktion get_type_hints
hinzugefügt wurde. Wenn Sie damit eine spezielle Typprüfung erstellen, können Sie den Typ einschließlich des Wertebereichs überprüfen.
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 ()
einen Gleitkomma einfügt, wird eine Warnung angezeigt, dass er veraltet ist, auch wenn er nach dem Dezimalpunkt 0 ist. Es scheint in Zukunft "TypeError" zu sein.random
-Modul kann jetzt jeder Datentyp als Startwert verwendet werden, solange er gehasht werden kann. Um jedoch sicherzustellen, dass das Ergebnis eindeutig ist, None
, int
, float
, Es können nur "str", "bytes and bytearray" gesetzt und verwendet werden.Hier ist eine Zusammenfassung der Änderungen in Python 3.9. Da sich 3.9 ebenfalls in der Beta befindet, denke ich, dass dieser Artikel fast vollständig ist, aber es gibt einige Optimierungsteile und Teile, die noch nicht geschrieben wurden, daher werde ich sie entsprechend hinzufügen.
Recommended Posts