2016-04-08 9 views
-3

Ich benutze Python 3.x. Könnte mir bitte jemand erklären, was file im folgenden Codeblock ist?Was ist das (in einer with-Anweisung)? Ist es eine Variable oder etwas anderes?

with open(filename, "a") as file: 
    file.write("Hello world") 
    print(file) #I added this line to try to understand what 'file' is. 

Wenn ich den obigen Code lief, print(file) dies erzeugt:

<_io.TextIOWrapper name='Class_A.txt' mode='a' encoding='cp1252'> 

ich das nicht verstehen. Ich kann sehen, dass es mit der with-Anweisung verwandt ist, aber es sieht nicht wirklich wie eine Variable aus.

Also was ist file? Ist es eine Variable oder etwas anderes? Wenn es eine Variable ist, welcher Datentyp ist es?

+1

Es * ist * eine Variable und speichert ein 'TextIOWrapper' Objekt. Wie ist das "nichts"? – deceze

+2

Warum sieht es nicht wie eine Variable aus? Warum speichert es nichts? Warum denkst du, dass es keine Variable ist? Es ist unklar von deiner Frage, wo die Verwirrung liegt. –

+3

Die Dokumentation ist [hier] (https://docs.python.org/3/reference/compound_stmts.html#with) frei verfügbar. – vaultah

Antwort

4

Ja, file ist eine Variable, die auf den von open() zurückgegebenen Kontextmanager verweist. Es ist zufällig das gleiche Objekt. Mit anderen Worten, file verweist auf ein Dateiobjekt.

Sie auch dies hätte tun können, um den gleichen Effekt hier:

file = open(filename, "a") 
try: 
    file.write("Hello world") 
finally: 
    file.close() 

so dass die Datei automatisch geschlossen wird. Das liegt daran, dass Dateiobjekte Kontextmanager sind; sie unterstützen die context manager protocol. Technisch gesehen ist die with context_manager as <name> Zielvariable an den Rückgabewert context_manager.__enter__() gebunden, aber ein Dateiobjekt gibt sich von dieser Methode zurück und die Methode file.__exit__() schließt die Datei. Siehe with compound statement documentation.

Wenn Sie nun Druck ein Objekt, das nicht eine String-Darstellung hat, wird es die repr() Funktion Druck:

>>> repr(open('/dev/null')) 
"<_io.TextIOWrapper name='/dev/null' mode='r' encoding='UTF-8'>" 
>>> print(repr(open('/dev/null'))) 
<_io.TextIOWrapper name='/dev/null' mode='r' encoding='UTF-8'> 

so ja, das ist nur eine andere Aufgabe, eine mit einem benutzerdefinierte, hilfreiche Darstellung. Datei-Objekte implementieren die object.__repr__() hook dies zu produzieren:

>>> open('/dev/null').__repr__() 
"<_io.TextIOWrapper name='/dev/null' mode='r' encoding='UTF-8'>" 

Der Name des Dateiobjekts kann auch verwirrend hier werden. Das liegt daran, dass Dateiobjekte in Python Teil einer Reihe von Objekten sind, die durch die io module definiert sind; ein TextIOWrapper object wickelt eine Puffer (hier ein BufferedReader, was wiederum die rohe, binäre Dateiobjekt in Form eines FileIO object wickeln:

>>> devnull = open('/dev/null', 'r') 
>>> devnull 
<_io.TextIOWrapper name='/dev/null' mode='r' encoding='UTF-8'> 
>>> devnull.buffer 
<_io.BufferedReader name='/dev/null'> 
>>> devnull.buffer.raw 
<_io.FileIO name='/dev/null' mode='rb' closefd=True> 

Das ist alles nur Tech-Detail, das Sie brauchen nicht normal Sorgen zu machen. führt Jedes Objekt eine bestimmte Funktion, und jemand, um erweiterte E/A-Gerangel tun können, diese mischen.

+0

Also 'Datei' ist eine Variable, die als Kontextmanager fungiert? – Kaiylar

+0

'Datei' ist ein Name, der auf ein Objekt verweist, das als Kontextmanager fungiert. –

+0

Ich verstehe nicht ... – Kaiylar

4

, dass die Textdarstellung eines Objekts ist, wenn er nicht seine eigene __repr__ oder __str__ hat. file ist eine Variable, die auf ein Objekt zeigt, das in der mit sta erstellt wurde ment.

3

Es ist das Objekt, das vom Kontextmanager-Aufruf open(filename, "a") zurückgegeben wird. Die _io.TextIOWrapper ist eine file-like object, die Sie mit Dingen wie lesen, schreiben, suchen und schließen können.

Wenn Sie dies tun:

with thing1 as thing2: 

Verfahren thing1.__enter__ aufgerufen wird, und was auch immer es gibt thing2 auf die Variable/Name zugewiesen wird.

Also ja, in Ihrem Beispiel ist file in der Tat eine Variable, die zu dem Objekt zugewiesen wurde, das vom with Kontextmanager zurückgegeben wurde. In diesem Fall ist es ein _io.TextIOWrapper Objekt. Aus diesem Grund, wenn Sie tun:

print(file) 

Sie erhalten:

<_io.TextIOWrapper name='Class_A.txt' mode='a' encoding='cp1252'> 

... das ist nur die String-Darstellung dieser Art von Objekt ist.

Sie können manuell das gleiche Objekt auf diese Weise erhalten:

file = open(filename, "a").__enter__() 
print(file) # same file-like object you were getting before 
file.write('a line') # do stuff with it 
file.close() # close it 

Beachten Sie, dass das Objekt zurück von open(filename, "a").__enter__() ist das gleiche Objekt, das Sie von open(filename, "a") bekommen würde. Dies liegt daran, dass die __enter__()-Methode des Objekts _io.TextIOWrapper einfach self zurückgibt. Dies ist jedoch bei anderen Objekten nicht immer der Fall.

Wenn Sie das alles verwirrend finden, empfehle ich, ein wenig mehr über die with statement zu lesen.

Verwandte Themen