2016-10-05 21 views
9

Używam nowego modułu Python 3.5 typing i jest on radosny.Moduł do pisania - typ literowy typu ciągowego

Zastanawiam się, jak można określić typ oparty na dokładnym dosłownym ciągu literowym. Na przykład funkcja gwarantuje zwrócenie jednego z czterech łańcuchów - "Północ", "Zachód", "Wschód", "Południe" - jak możemy wyrazić to jako konkretną zmienną typu, zamiast tylko str.

Przeglądałem dokumentację, znalezienie typ Union i funkcję TypeVar, ale nie był w stanie znaleźć odpowiedź

przykładowy funkcji wyrażającej ten problem.

def compute_quadrant(x: int, y: int) -> str: 
    if x > 0 and y > 0: 
     return 'I' 
    elif x < 0 and y > 0: 
     return 'II' 
    elif x < 0 and y < 0: 
     return 'III' 
    elif x > 0 and y < 0: 
     return 'IV' 

Zamiast powrocie str, ja lubię zwrócić bardziej specyficzny typ, który jest jedną z czterech wartości - "I", "II", "III" lub "IV".

W Maszynopisie można zrobić: type Quadrant = "I" | "II" | "III" | "IV" - czy jest jakiś miły cukier Python do tego zastosowania z modułem typing?

+5

Nie związane z pisaniem, ale czy brałeś pod uwagę "wyliczenie"? –

+0

Czy mogę zapytać, dlaczego potrzebujesz czegoś takiego? Ponieważ adnotacje typu są tworzone dla edytorów tekstu i programistów wyświetlających kod. Jeśli możesz ograniczyć zakres elementów, które funkcja mogłaby zwrócić, to na pewno możesz to powiedzieć, patrząc na kod. –

+0

Być może ta konkretna funkcja nie wskazywała przypadku użycia (ponieważ jest prosta i prosta), ale podczas pisania kodu chciałbym zaoferować mojemu rówieśnikowi jak najwięcej kontekstu. Podczas manipulowania danymi i wykonywania skomplikowanych operacji na obiektach chciałbym móc oferować bardzo dokładne i dokładne typy. Ponadto narzędzia analityczne są w stanie znaleźć punkty optymalizacji na podstawie typów - takich jak ścieżki kodowe, które nigdy nie zostaną trafione, lub rażące błędy. – fructosewizard

Odpowiedz

1

Pominąwszy moduł typing, o który pytałeś, jednym z rozwiązań twojego problemu może być użycie Enum, jak ma to miejsce w wielu komentarzach. Kod tego będzie wyglądał następująco:

from enum import Enum 

class Quadrant(Enum): 
    I = 1 
    II = 2 
    III = 3 
    IV = 4 

def compute_quadrant(x: int, y: int) -> Quadrant: 
    if x > 0 and y > 0: 
     return Quadrant.I 
    elif x < 0 and y > 0: 
     return Quadrant.II 
    elif x < 0 and y < 0: 
     return Quadrant.III 
    elif x > 0 and y < 0: 
     return Quadrant.IV 
    # return None # this is what happens without an else clause! 

if __name__ == "__main__": 
    quad = compute_quadrant(1, -1) 
    print(quad, type(quad))    # -> Quadrant.IV <enum 'Quadrant'> 
    print(quad.name, type(quad.name)) # -> IV <class 'str'> 
    print(quad.value, type(quad.value)) # -> 4 <class 'int'> 

Jak widać, możesz użyć nazwy i wartości Enums. Nazwa jest jednym z żądanych łańcuchów.

Jedną z kwestii, którą tu widzę, jest brakująca klauzula else w funkcji i obecne zachowanie mypy w zakresie przyjmowania None jako poprawnej wartości zwracanej dla Quadrant. To powinno być obsługiwane ręcznie.