Geben Sie Hinweise ein, die in PEP484 seit Python 3.5 hinzugefügt wurden. Ich habe mich gefragt, ob es auf das ndarray von numpy angewendet werden kann, daher handelt es sich um ein statisches Prüftool für Typhinweise mypy. ) Und die Ergebnisse von ww-Untersuchungen wie dem Umgang mit Modulen von Drittanbietern werden zusammengefasst.
Zusammenfassend lässt sich sagen, dass die Überprüfung von Tippangaben für numpy.ndarray mithilfe von mypy mithilfe von numpy-stubs möglich ist. Ab sofort (Januar 2020) ist eine Mypy-Überprüfung durch Angabe des Typs und der Form von ndarray jedoch nicht möglich. Wenn Sie dagegen Typhinweise wie dtype und shape als Anmerkungen zur besseren Lesbarkeit hinzufügen möchten, ist die Option nptyping gut.
Installieren Sie mindestens Folgendes mit pip
. (Die Umgebung in Klammern ist die Umgebung zum Zeitpunkt meiner Überprüfung.)
Zuallererst war die Typprüfung unsicher, also habe ich experimentiert.
# ex1.py
from typing import List, Tuple
def calc_center(points: List[Tuple[int, int]]) -> Tuple[float, float]:
'''Finden Sie den Schwerpunkt aus der Liste der Punkte'''
n = len(points)
x, y = 0, 0
for p in points:
x += p[0]
y += p[1]
return x/n, y/n
points_invalid = [[1, 1], [4, 2], [3, 6], [-1, 3]]
print(calc_center(points_invalid)) # TypeHint Error
Der obige Code endet natürlich normal, aber ich werde den Typhinweis mit mypy überprüfen. Wenn Sie mypy mit pip usw. installiert haben, sollten Sie in der Lage sein, "mypy" im Terminal auszuführen.
>mypy ex1.py
ex1.py:16: error: Argument 1 to "calc_center" has incompatible type "List[List[int]]"; expected "List[Tuple[int, int]]"
Found 1 error in 1 file (checked 1 source file)
>python ex1.py
(1.75, 3.0)
Auf diese Weise wird darauf hingewiesen, wo der Typhinweis verletzt wird. Wenn Sie es wie folgt ändern, besteht die Prüfung durch mypy.
# ex2.py
from typing import List, Tuple
def calc_center(points: List[Tuple[int, int]]) -> Tuple[float, float]:
'''Finden Sie den Schwerpunkt aus der Liste der Punkte'''
n = len(points)
x, y = 0, 0
for p in points:
x += p[0]
y += p[1]
return x/n, y/n
points = [(1, 1), (4, 2), (3, 6), (-1, 3)]
print(calc_center(points)) # Success
>mypy ex2.py
Success: no issues found in 1 source file
Da Numpys ndarray für die Berechnung von Koordinatenpunkten praktisch ist, möchte ich es entsprechend ändern. Wenn ich jedoch dem vorherigen Code "import numpy" hinzufüge und mypy ausführe, tritt der folgende Fehler auf.
# ex3.py
from typing import List, Tuple
import numpy as np
def calc_center(points: List[Tuple[int, int]]) -> Tuple[float, float]:
'''Finden Sie den Schwerpunkt aus der Liste der Punkte'''
n = len(points)
x, y = 0, 0
for p in points:
x += p[0]
y += p[1]
return x/n, y/n
points = [(1, 1), (4, 2), (3, 6), (-1, 3)]
print(calc_center(points)) # Success
>mypy ex3.py
ex3.py:4: error: No library stub file for module 'numpy'
ex3.py:4: note: (Stub files are from https://github.com/python/typeshed)
Found 1 error in 1 file (checked 1 source file)
Die Ursache des Fehlers ist, dass das numpy-Paket selbst keine Typhinweise unterstützt. Teilen wir dann die Gegenmaßnahmen in die folgenden drei Fälle ein.
Dies scheint die einfachste und häufigste zu sein. Die Methode besteht darin, eine Datei mit dem Namen mypy.ini zu erstellen, wie folgt zu schreiben und sie dann in das aktuelle Verzeichnis zu stellen.
[mypy]
[mypy-numpy]
ignore_missing_imports = True
In der 3. und 4. Zeile wird der Fehler beim Überprüfen des Typhinweises für numpy ignoriert. Wenn Sie es auf andere Module von Drittanbietern anwenden möchten, kopieren Sie die 3. und 4. Zeile und ändern Sie den Teil "numpy". Weitere Spezifikationen zu mypy.ini finden Sie auf der offiziellen Seite hier.
Jetzt können Sie mypy check normal ausführen. Beachten Sie jedoch, dass die Typhinweiseprüfung von ndarray selbst ebenfalls ignoriert wird (letzte Zeile).
# ex4.py (ignore_missing_imports)
from typing import List, Tuple
import numpy as np
def calc_center(points: List[Tuple[int, int]]) -> Tuple[float, float]:
'''Finden Sie den Schwerpunkt aus der Liste der Punkte'''
n = len(points)
x, y = 0, 0
for p in points:
x += p[0]
y += p[1]
return x/n, y/n
def calc_center_np(points: np.ndarray) -> np.ndarray:
'''Finden Sie den Schwerpunkt aus der Liste der Punkte(ndarray Version)'''
return np.average(points, axis=0)
points = [(1, 1), (4, 2), (3, 6), (-1, 3)]
print(calc_center(points)) # Success
np_points = np.array(points, dtype=np.int)
print(calc_center_np(np_points)) # Success
print(calc_center_np(points)) # Success ?
>mypy ex4.py
Success: no issues found in 1 source file
Erstellen Sie eine leere Funktion (Stub) für den Typhinweis des Moduls, das Sie verwenden möchten, und mypy betrachtet sie stattdessen. Stub-Dateien werden mit der Erweiterung .pyi verwaltet.
Ein Stub für numpy numpy-stubs ist auf github verfügbar.
Bringen Sie zuerst den Ordner "numpy-stubs" mit "git clone https: // github.com / numpy / numpy-stubs.git" usw. Ändern Sie den Ordner "numpy-stubs" in "numpy".
Die Ordnerstruktur ist wie folgt.
numpy-stubs/
└── numpy
├── __init__.pyi
└── core
├── numeric.pyi
├── numerictypes.pyi
├── _internal.pyi
└── __init__.pyi
Fügen Sie außerdem den Stammordnerpfad, in dem sich der Stub befindet, zur Umgebungsvariablen MYPYPATH
hinzu und führen Sie ihn aus.
# ex5.py (numpy-stubs)
from typing import List, Tuple
import numpy as np
def calc_center(points: List[Tuple[int, int]]) -> Tuple[float, float]:
'''Finden Sie den Schwerpunkt aus der Liste der Punkte'''
n = len(points)
x, y = 0, 0
for p in points:
x += p[0]
y += p[1]
return x/n, y/n
def calc_center_np(points: np.ndarray) -> np.ndarray:
'''Finden Sie den Schwerpunkt aus der Liste der Punkte(ndarray Version)'''
return np.average(points, axis=0)
points = [(1, 1), (4, 2), (3, 6), (-1, 3)]
print(calc_center(points)) # Success
np_points = np.array(points, dtype=np.int)
np_points_float = np.array(points, dtype=np.float)
print(calc_center_np(np_points)) # Success
print(calc_center_np(np_points_float)) # Success
print(calc_center_np(points)) # TypeHint Error
>set "MYPYPATH=numpy-stubs"
>mypy ex5.py
ex5.py:28: error: Argument 1 to "calc_center_np" has incompatible type "List[Tuple[int, int]]"; expected "ndarray"
Found 1 error in 1 file (checked 1 source file)
Jetzt funktioniert die Typhinweiseprüfung von ndarray selbst. Es ist jedoch nicht möglich, nach Angabe von Typ und Form zu überprüfen, und es ist ein kleiner Engpass, dass Umgebungsvariablen einzeln festgelegt werden müssen.
stubgen
mypy wird mit einem Skript namens stubgen geliefert, das automatisch eine Datei für Typhinweise generiert (Erweiterung .pyi). ..
>stubgen -p numpy
-p
ist eine Option zum rekursiven Generieren von Stubs für Pakete.
Bei der Ausführung wird im aktuellen Verzeichnis ein "out" -Ordner erstellt und die numpy-Stub-Datei darin gepackt.
Beim Ausführen von mypy check wird jedoch ein weiterer Fehler angezeigt, wahrscheinlich weil stubgen die Struktur von numpy nicht gut extrahieren kann. Es gibt Fälle, in denen Stubs wie Numpy-Stubs für die Öffentlichkeit zugänglich sind. Daher ist es sicherer, diese nach Möglichkeit zu verwenden.
Wenn Sie einen Typ-Hinweis erstellen möchten, der dtype und die Form von ndarray enthält, nachdem Sie entweder Methode 1 oder Methode 2 gewählt haben, [nptyping](numpy-type-hints-in-python-pep- 484) sollte verwendet werden.
Es kann von PyPi mit pip install nptyping
installiert werden.
Obwohl nptyping die Überprüfung statischer Typhinweise durch mypy nicht unterstützt, können Typhinweise, die den Typ und die Form von ndarray angeben, mit dem Alias Array
angegeben werden.
Unten finden Sie ein offizielles Beispiel. Arrays mit gemischten Typen wie DataFrame von Pandas sind ebenfalls in Ordnung.
from nptyping import Array
Array[str, 3, 2] # 3 rows and 2 columns
Array[str, 3] # 3 rows and an undefined number of columns
Array[str, 3, ...] # 3 rows and an undefined number of columns
Array[str, ..., 2] # an undefined number of rows and 2 columns
Array[int, float, str] # int, float and str on columns 1, 2 and 3 resp.
Array[int, float, str, ...] # int, float and str on columns 1, 2 and 3 resp.
Array[int, float, str, 3] # int, float and str on columns 1, 2 and 3 resp. and with 3 rows
Eine Instanzprüfung mit is instance
ist ebenfalls möglich.
# ex6.py (nptyping)
from typing import List, Tuple
import numpy as np
from nptyping import Array
def calc_center(points: List[Tuple[int, int]]) -> Tuple[float, float]:
'''Finden Sie den Schwerpunkt aus der Liste der Punkte'''
n = len(points)
x, y = 0, 0
for p in points:
x += p[0]
y += p[1]
return x/n, y/n
def calc_center_np(points: Array[int, ..., 2]) -> Array[float, 2]:
'''Finden Sie den Schwerpunkt aus der Liste der Punkte(ndarray Version)'''
print(isinstance(points, Array[int, ..., 2]))
return np.average(points, axis=0)
points = [(1, 1), (4, 2), (3, 6), (-1, 3)]
np_points = np.array(points, dtype=np.int)
np_points_float = np.array(points, dtype=np.float)
print(isinstance(calc_center_np(np_points), Array[float, 2])) #Streit: True,Rückgabewert: True
print(isinstance(calc_center_np(np_points_float), Array[float, 2])) #Streit: False,Rückgabewert: True
print(isinstance(calc_center_np(points), Array[float, 2])) #Streit: False,Rückgabewert: True
Vergessen Sie nicht, nptyping in mypy.ini auf "ignore_missing_imports = True" zu setzen. Das Ausführungsergebnis ist wie folgt.
>mypy ex6.py
Success: no issues found in 1 source file
>python ex6.py
True
True
False
True
False
True
Ich habe die Typhinweise rund um Numpy zusammengefasst. Ich denke, es ist üblich, Informationen wie Koordinaten und Tabellendaten als ndarray zu behandeln und geometrische und statistische Operationen zu implementieren. Zu dieser Zeit mache ich mir oft Sorgen um den Code, den ich geschrieben habe, wie zum Beispiel "Wie viele Dimensionen von Ndarray kneten Sie?" Ich fand Typhinweise wie nptyping nützlich in Bezug auf Lesbarkeit und Wartbarkeit. Ich denke, dass es nützlicher sein wird, wenn es in Zukunft die Typprüfung durch mypy unterstützen kann.
https://stackoverflow.com/questions/52839427/ https://www.sambaiz.net/article/188/ https://masahito.hatenablog.com/entry/2017/01/08/113343
Recommended Posts