2017-09-22 8 views
0

Ich habe eine Funktion, die ein 2-Tupel aber optional ein 3-Tupel zurückgibt. Wie beschreibe ich dies mit Typ Anmerkungen?Python-Typ Anmerkungen: Element im Tupel als optional markieren

Zum Beispiel:

from typing import Tuple 

def example(i): 
    # type: (int) -> Tuple[int, int, <what to put here?>] 
    if i < 10: 
     return (i, i+1, 1) 
    else: 
     return (i, i+1) 

Ich Union wie unten verwenden kann, aber es scheint ziemlich chaotisch.

+1

Das sind 2 verschiedene Arten. Die Vereinigung ist wahrscheinlich die logischste. – Carcigenicate

Antwort

2

Wie in den Kommentaren darauf hingewiesen, ist die Union wahrscheinlich der bessere Ansatz. Wenn die Signatur unordentlich aussieht, können Sie type aliases wie so verwenden:

from typing import Tuple, Union 

MyType = Union[Tuple[int, int], Tuple[int, int, int]] 

def example1(i): 
    # type: (int) -> MyType 
    ...snip... 

Ein alternativer Ansatz wäre es, die "indefinite length" Tuple type zu verwenden. Sie würden im Grunde geben, die genaue Länge des Tupels zu kodieren, aber im Gegenzug können Sie den Rückgabetyp normalisieren und diese Vereinigung vermeiden. (Wenn Ihr Code auf die Länge verlässt, ist dies wahrscheinlich nicht der beste Ansatz). Ein etwas drastischerer Ansatz wäre es, eine Restrukturierung Ihres Codes zu erwägen, um diese Art von Situation zu vermeiden.

Schließlich, wenn Sie diese zwei verschiedenen Typen zurückgeben, wird der Aufrufer Ihrer Funktion wahrscheinlich sowieso die Länge überprüfen müssen, nicht wahr?

In diesem Fall besteht eine Idee darin, ein Tupel zurückzugeben und stattdessen entweder eine NamedTuple oder eine benutzerdefinierte Klasse zurückzugeben, die beide ein optionales Feld haben. Sie können dann Ihre "Länge" -Kontrolle in ein "ist dieses Feld auf keine gesetzt" umwandeln.

Ich nehme an, in gewissem Sinne erfüllt der NamedTuple-Ansatz auch Ihre ursprüngliche Anfrage in gewisser Weise, solange es Ihnen nichts ausmacht, Ihre Tupel zu konvertieren/den zusätzlichen Overhead.

from typing import NamedTuple, Optional 

MyType2 = NamedTuple('MyType2', (
    ('x', int), 
    ('y', int), 
    ('z', Optional[int]), 
)) 

class MyType3(object): 
    def __init__(self, x, y, z): 
     # type: (int, int, Optional[int]) -> None 
     self.x = x 
     self.y = y 
     self.z = z 

(Der „individuelle Klasse“ Ansatz wird wahrscheinlich mehr elegant sein, wenn PEP 557 akzeptiert und in die Sprache integriert).

Der andere Ansatz besteht darin, Ihre Funktion in zwei aufzuteilen, wenn Sie im Voraus wissen, welche Art von Tupel Sie erwarten. Dann können Sie einfach die Funktion des entsprechenden Typs aufrufen.

+0

Vielen Dank für die gründliche Antwort. –

Verwandte Themen