2016-12-22 7 views
21

In Python 3.6 wurden die neuen Variable Annotations in der Sprache eingeführt.Nameerror Inkonsistenz Variablentyp Anmerkung

Aber, wenn ein Typ nicht vorhanden ist, die zwei verschiedene Dinge passieren kann:

>>> def test(): 
...  a: something = 0 
... 
>>> test() 
>>> 
>>> a: something = 0 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
NameError: name 'something' is not defined 

Warum ist die nicht vorhandene Art Handhabung Verhalten anders? Würde es nicht dazu führen, dass man die undefinierten Typen in den Funktionen übersieht?


Hinweise

Versuchten mit sowohl Python 3.6 RC1 und RC2 - gleiches Verhalten.

PyCharm hebt something als „ungelöste reference“ in sowohl innerhalb als auch außerhalb der Funktion.

+0

http://stackoverflow.com/questions/39971929/what-are-variable-annotations-in-python-3-6 – McNets

Antwort

14

Das Verhalten der lokalen Variablen (in der Funktion ie) ist zumindest in dem Abschnitt dokumentiert Runtime Effects of Type Annotations:

eine lokale Variable mit Anmerkungen versehen wird, den Interpreter veranlassen, als ein lokaler zu behandeln, auch wenn es nie zugewiesen. Anmerkungen für lokale Variablen werden nicht ausgewertet:

def f(): 
    x: NonexistentName # No error. 

Und geht auf den Unterschied für globale Variablen zu erklären:

Wenn es jedoch an einem Modul oder Klassenstufe ist, dann ist der Typ

x: NonexistentName # Error! 
class X: 
    var: NonexistentName # Error! 

Das Verhalten scheint überraschend für mich, so kann ich nur meine Vermutung in Bezug auf die r bieten: wird ausgewertet easoning: Wenn wir den Code in ein Modul einfügen, möchte Python die Annotationen speichern.

# typething.py 
def test(): 
    a: something = 0 

test() 


something = ... 

a: something = 0 

Dann importieren:

>>> import typething 
>>> typething.__annotations__ 
{'a': Ellipsis} 
>>> typething.test.__annotations__ 
{} 

Warum es notwendig ist, es auf dem Modulobjekt zu speichern, aber nicht auf die Funktion Objekt - Ich habe noch keine gute Antwort haben. Vielleicht aus Performance-Gründen, da die Annotationen durch statische Code-Analyse gemacht werden und diese Namen sich dynamisch ändern können:

... Der Wert der lokal verfügbaren Annotationen kompensiert nicht die Kosten für das Erstellen und Füllen das Annotationswörterbuch bei jedem Funktionsaufruf. Daher werden Annotationen auf Funktionsebene nicht ausgewertet und nicht gespeichert.

+1

Vielleicht möchten sie Probleme mit der Definition einer lokalen Klasse "C" innerhalb einer Funktion vermeiden und dann Variablen in der Funktion mit "C" annotieren. "C" existiert nicht, bis seine Definition ausgeführt wird. Sie können es also nicht in einem Attribut "__annotations__" zur Funktionsdefinitionszeit speichern. – user2357112

+0

Gotcha! Die Performance-Argumentation macht Sinn, ich frage mich, ob dies zu Problemen führen würde, wenn Sie einen variablen Typ in einer Funktion vertippen..ich denke, dass intelligente Editoren und Tests dabei helfen sollten. Vielen Dank! – alecxe

4

Sie können zu https://www.python.org/ftp/python/3.6.0/ gehen und die RC2-Version herunterladen, um Anmerkungen zu testen, aber die freigegebene Version, wie bereits erwähnt, ist noch nicht veröffentlicht. Ich habe jedoch Ihren Code mit dem Python3.6-Interpreter heruntergeladen und ausprobiert, und es traten keine Fehler auf.

+0

Ah, ich habe die Python 3.6.0rc1, lassen Sie mich mit Python 3.6.0rc2 überprüfen. Vielen Dank! – alecxe

+2

@Dilmer: Keine Fehler aufgetaucht? Das ist merkwürdig. Ich würde erwarten, dass der Fehler in beiden Fällen erhöht wird. – BrenBarn

+0

Keine Fehler "Python 3.6.0rc2 (v3.6.0rc2: 800a67f7806d, 16. Dezember 2016, 14:12:21)" die Testfunktion hinzugefügt und es als test() aufrufen und Ergebnis bereinigen. – Dilmer

7

Die direkte Antwort für diese (ergänzen @ Antwort wims) stammt aus dem issue tracker on Github, wo der Vorschlag diskutiert wurde:

[..] Schließlich Einheimische. Hier denke ich, dass wir die Typen nicht speichern sollten - Der Wert, die Anmerkungen lokal verfügbar zu haben, ist gerade nicht genug, um die Kosten des Erstellens und Bestückens des Wörterbuchs bei jedem Funktionsaufruf auszugleichen.

In der Tat, Ich glaube nicht einmal, dass die Art Ausdruck sollte während der Ausführung der Funktion ausgewertet werden. Also zum Beispiel:

def side_effect(): 
    print("Hello world") 
def foo(): 
    a: side_effect() 
    a = 12 
    return a 
foo() 

sollte nichts drucken. (A Typprüfer würde auch beklagen, dass side_effect() ist kein gültiger Typ.)

Vom BDFL selbst :-) noch ein dict geschaffen noch Auswertung durchgeführt wird.

Derzeit Funktion nur Objekte speichern Annotationen wie in ihrer Definition geliefert:

def foo(a: int): 
    b: int = 0 

get_type_hints(foo) # from typing 
{'a': <class 'int'>} 

war offenbar zu teuer als ein anderes Wörterbuch für die lokalen Variable Anmerkungen anlegen.

-1

Sie können wie folgt versuchen schreiben:

>>>a: 'something' = 0 
+0

Hm, das ist leider nicht der Punkt der Frage. –