2016-03-29 38 views
16

Attualmente sto lavorando alla creazione di un modulo di algebra lineare python per il divertimento e la pratica con la lingua. Recentemente ho provato ad aggiungere annotazioni di tipo al modulo, come ad esempio:Nome non definito nell'annotazione del tipo

class Vector: 
    # Various irrelevant implementation details 
    def __add__(self, other: Vector) -> Vector: 
     # More implementation details.... 

Tuttavia, quando provo ad importare questo, sputa fuori un NameError: Name 'Vector' is not defined. Riconosco che questa domanda ha già ricevuto risposta, in un modulo, here, ma non sembra fornire una risposta completa alla mia situazione.

Che mi piacerebbe sapere:

  • Ho definito la classe letteralmente in questo file. Perché dice che il nome non è definito?
  • Come si definisce Vector in modo che possa essere utilizzato per le annotazioni (come type)?
+0

Si prega di mantenere il tuo indirizzo limitato a ** una ** domanda per posta. Qui ci sono 2 domande distinte, una sulla dipendenza circolare (metodi della classe che dipendono dalla classe prima che sia stata creata) e sulla differenza tra un tipo e una classe. Quest'ultimo è un duplicato. –

+0

Vedi [Class vs.Digitare in Python] (https://stackoverflow.com/q/35958961) per la parte della domanda che ho rimosso dal tuo post. –

+0

Siamo spiacenti. Pensavo che la domanda tipo fosse pertinente al problema in questione. – BHustus

risposta

21

Hai una dichiarazione in avanti; le funzioni (da associare come metodi) vengono create prima della classe, quindi il nome Vector non esiste ancora. Solo quando tutto il corpo della classe è stato eseguito, Python può creare l'oggetto class e associare il nome Vector ad esso.

Basta utilizzare una stringa con il nome invece:

class Vector: 
    # Various irrelevant implementation details 
    def __add__(self, other: 'Vector') -> 'Vector': 
     # More implementation details.... 

questo non influisce come il vostro IDE vede la dichiarazione; le stringhe vengono cercate una volta caricato l'intero modulo e vengono risolte come un'espressione Python valida nel contesto corrente. Poiché la classe Vector esiste una volta caricato l'intero modulo, la stringa 'Vector' può essere correttamente convertita nell'oggetto classe.

vedere anche la specification on forward references:

Quando un tipo di suggerimento contiene i nomi che non sono state ancora definite, tale definizione può essere espresso come una stringa letterale, da risolvere in seguito.

[...]

La stringa letterale dovrebbe contenere un'espressione Python valida [...] e dovrebbe valutare senza errori una volta che il modulo è stato completamente caricato.

+0

Grazie. Avevo visto la risposta stringa nella domanda collegata, ma ciò che mi ha buttato fuori era che stava evidenziando 'altro: Vector' con il colore della classe, e' -> Vector' senza, quindi quando ho commentato il secondo Vector non ho mai pensato di necessario per farlo per il primo. Grazie per il chiarimento. – BHustus

1

Se si utilizza Python 3.7 e superiori. Date un'occhiata a Postponed evaluation of annotations

Dal Python 3.7, sarà consentito, basta aggiungere:

from __future__ import annotations 

e si noti anche che

che diventerà il default in Python 4.0.

+1

Questo è interessante da notare. Ho intenzione di lasciare la risposta così com'è perché funziona per tutte le versioni 3.x (o almeno, più versioni 3.x rispetto alla soluzione 'import annotations'), ma sono comunque felice che tu abbia postato questo qui. – BHustus