[PYTHON] Ich wollte auch Typhinweise mit numpy überprüfen

Überblick

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.

Fazit

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.

Vorbereitung

Installieren Sie mindestens Folgendes mit pip. (Die Umgebung in Klammern ist die Umgebung zum Zeitpunkt meiner Überprüfung.)

Typprüfung von mypy

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

Typprüfung für Module von Drittanbietern

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.

Methode 1. Ignorieren Sie Hinweise von Drittanbietern

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

Methode 2. Erstellen Sie einen Stub für Typhinweise

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.

Methode 3. Verwenden Sie auch nptyping

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

Zusammenfassung

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.

Referenzartikel

https://stackoverflow.com/questions/52839427/ https://www.sambaiz.net/article/188/ https://masahito.hatenablog.com/entry/2017/01/08/113343

Recommended Posts

Ich wollte auch Typhinweise mit numpy überprüfen
Ich wollte ABC160 mit Python lösen
Ich wollte ABC172 mit Python lösen
Ich wollte unbedingt mit Selen kopieren
Ich wollte den NOMURA Contest 2020 mit Python lösen
Ich wollte mit der Bezier-Kurve spielen
Ich wollte Python 3.4.3 mit Homebrew + pyenv installieren
Ich möchte ein Element mit numpy in eine Datei schreiben und es überprüfen.
Ich habe GP mit Numpy geschrieben
Ich wollte den Panasonic Programming Contest 2020 mit Python lösen
Ich habe versucht, mit Quantx einen Ausbruch (Typ der Täuschungsvermeidung) zu implementieren
Ich möchte mit Numpy die japanische Flagge in die Palau-Flagge ändern
Ich habe das Toho-Projekt mit Deep Learning aufgenommen ... ich wollte.
Ich wollte ein Array mit der Subs-Methode von Sympy berechnen
Ich wollte mit boto3 mehrere objekte in s3 löschen
Trainieren! !! Einführung in Python Type (Type Hints)
Ich wollte eine intelligente Präsentation mit Jupyter Notebook + nb present erstellen
Hash-Kette wollte ich vermeiden (2)
Ich wollte cGAN zu ACGAN weiterentwickeln
Erhöhen Sie die Sichtbarkeit der Quelle mit Typhinweisen
Ich wollte das ABC164 A ~ D-Problem mit Python lösen
Ich möchte ○○ mit Pandas machen
Ich möchte die Position meines Gesichts mit OpenCV überprüfen!
Ich möchte mit Python debuggen
Hash-Kette wollte ich vermeiden (1)
Deshalb beende ich Pandas [Drei Möglichkeiten, um groupby.mean () mit nur NumPy]
Ich habe versucht, Deep Learning zu implementieren, das nicht nur mit NumPy tiefgreifend ist
Ich wollte ein Jupyter-Notebook mit Docker in einer Pip-Umgebung (Opticspy) verwenden.
Verwenden Sie Python aus Java mit Jython. Ich war auch süchtig danach.
Es ist neuer, aber ich wollte die BMI-Berechnung mit Python ausprobieren.
Ich habe mit Python mit dem maschinellen Lernen begonnen (ich habe auch angefangen, in Qiita zu posten). Datenvorbereitung
Ich möchte Objekte mit OpenCV erkennen
[Python] Einfache Überprüfung des Argumenttyps mit Datenklasse
Ich habe versucht, Autoencoder mit TensorFlow zu implementieren
Ich habe versucht, AutoEncoder mit TensorFlow zu visualisieren
Ich habe versucht, mit Hy anzufangen
Ich möchte einen Blog mit Jupyter Notebook schreiben
Ich möchte eine Pip-Installation mit PythonAnywhere durchführen
Ich möchte Protokolle mit Python analysieren
Ich möchte mit aws mit Python spielen
[Einführung in Pytorch] Ich habe mit sinGAN ♬ gespielt
Ich wollte ABC159 mit Python lösen
Ich habe versucht, CVAE mit PyTorch zu implementieren
Ich habe ein Lebensspiel mit Numpy gemacht
Ich habe versucht, TSP mit QAOA zu lösen
DQN mit TensorFlow implementiert (ich wollte ...)
Ich wollte die 3D-Partikelsimulation mit der Python-Visualisierungsbibliothek Matplotlib visualisieren.
Ich möchte mkl mit numpy und scipy unter pyenv + Poesie verwenden
Ich habe versucht, eine Umgebung zu erstellen, um regelmäßig mit Selenium mit AWS Fargate zu überprüfen
Möchten Sie Python-Dekoratoren Typhinweise hinzufügen?
Ich habe versucht, das Lesen von Dataset mit PyTorch zu implementieren
Ich habe versucht, lightGBM, xg Boost mit Boruta zu verwenden
Ich möchte MATLAB feval mit Python verwenden
Konvertieren Sie Daten mit Form (Anzahl der Daten, 1) in (Anzahl der Daten,) mit numpy.
Ich habe versucht, mit TF Learn die logische Operation zu lernen
Ich habe versucht, GAN (mnist) mit Keras zu bewegen
i-Town Page Scraping: Ich wollte den Platz von Wise-Kun einnehmen
Fügen Sie einem leeren Array mit numpy Zeilen hinzu