Warum ist die gedruckte Klammer in Python 2.7 freiwillig?

98

In Python 2.7 machen beide die gleichen Schritte

print("Hello, World!") # Prints "Hello, World!"

print "Hello, World!" # Prints "Hello, World!"

Das Folgende wird jedoch nicht

print("Hello,", "World!") # Prints the tuple: ("Hello,", "World!")

print "Hello,", "World!" # Prints the words "Hello, World!"

In Python 3.x ist die Klammer on printobligatorisch, was sie im Wesentlichen zu einer Funktion macht. In 2.7 funktionieren beide jedoch mit unterschiedlichen Ergebnissen. Was sollte ich sonst noch printin Python 2.7 wissen ?

Hubro
quelle
7
In Python 2.x printist eigentlich eine spezielle Anweisung, keine Funktion. Dies ist auch der Grund, warum es nicht wie folgt verwendet werden kann: lambda x: print xBeachten Sie, dass (expr)kein Tupel erstellt wird (was dazu führt expr), aber dies ,tut.
Ich gehe davon aus, dass die Unterstützung für Druck als Funktion und Druck als Anweisung darin besteht, die Abwärtskompatibilität mit älteren Python-Versionen aufrechtzuerhalten und gleichzeitig die Benutzer zu ermutigen, die neue Syntax für die Migration in Richtung Python 3 zu verwenden.
GWW
11
ps, Um die Druckfunktion in 2.7 zu aktivieren (und nicht das Verhalten der Druckanweisung zu haben), müssen Sie einen zukünftigen Import durchführen:from __future__ import print_function
Jeff Mercado
Wird das zweite Beispiel tatsächlich "Hallo Welt!" (ohne Leerzeichen) oder wird "Hallo Welt!" (mit dem Leerzeichen) wie im Beispiel.
Kapad

Antworten:

106

In Python 2.x printist eigentlich eine spezielle Anweisung und keine Funktion *.

Dies ist auch der Grund, warum es nicht verwendet werden kann wie: lambda x: print x

Beachten Sie, dass (expr)kein Tupel erstellt wird (dies führt zu expr), aber dies ,tut. Dies führt wahrscheinlich zu einer Verwechslung zwischen print (x)und print (x, y)in Python 2.7

(1)   # 1 -- no tuple Mister!
(1,)  # (1,)
(1,2) # (1, 2)
1,2   # 1 2 -- no tuple and no parenthesis :) [See below for print caveat.]

Da es sich jedoch in Python 2.x printum ein spezielles Syntaxanweisungs- / Grammatikkonstrukt handelt , werden die ohne Klammer auf ,besondere Weise behandelt - und es wird kein Tupel erstellt. Diese spezielle Behandlung der printAussage ermöglicht es ihr, anders zu handeln, ob es ein Trailing gibt ,oder nicht.

Viel Spaß beim Codieren.


* Dieses printVerhalten in Python 2 kann in das von Python 3 geändert werden:

from __future__ import print_function
user2357112 unterstützt Monica
quelle
3
Danke für die (expr) != tupleErklärung :-)
Hubro
5

Es ist alles sehr einfach und hat nichts mit Vorwärts- oder Abwärtskompatibilität zu tun.

Die allgemeine Form für die printAnweisung in allen Python-Versionen vor Version 3 lautet:

print expr1, expr2, ... exprn

(Jeder Ausdruck wird ausgewertet, in eine Zeichenfolge konvertiert und mit einem Leerzeichen dazwischen angezeigt.)

Denken Sie jedoch daran, dass das Setzen von Klammern um einen Ausdruck immer noch der gleiche Ausdruck ist.

Sie können dies also auch schreiben als:

print (expr1), (expr2), ... (expr3)

Dies hat nichts mit dem Aufruf einer Funktion zu tun.

Don O'Donnell
quelle
Dies ist eine vollkommen korrekte Antwort. Ich bin mir nicht sicher, warum sie auch so stark herabgestuft wurde.
Martijn Pieters
Es geht nicht darum print (expr1), (expr2), ... (expr3), warum print (expr1, expr2, ... , expr3)es in Python 2.x legal ist, während es nicht den 2.x-Standards entsprechen sollte.
Vinnief
5

Hier haben wir interessante Nebenwirkungen, wenn es um UTF-8 geht.

>> greek = dict( dog="σκύλος", cat="γάτα" )
>> print greek['dog'], greek['cat']
σκύλος γάτα
>> print (greek['dog'], greek['cat'])
('\xcf\x83\xce\xba\xcf\x8d\xce\xbb\xce\xbf\xcf\x82', '\xce\xb3\xce\xac\xcf\x84\xce\xb1')

Der letzte Druck ist ein Tupel mit hexadezimalen Bytewerten.

Karlo Smid
quelle
7
Ich nehme an, das liegt daran, dass print UTF-8 korrekt druckt, aber wenn es wie Ihr letzter Druck ein Tupel empfängt, wird es reprdarauf ausgeführt. Zu diesem Zeitpunkt codiert es wahrscheinlich alle Zeichenfolgen im Diktat in ASCII.
Hubro
3
@Codemonkey, Sie haben Recht mit Repr . Sie liegen falsch in Bezug auf ASCII. ASCII ist die Standardcodierung für Python. Aber ich habe am Anfang des Python-Skripts #encoding=utf-8Linux env LANG=en_US.UTF-8. So repr Encodierungen mit Standard ASCII nicht, aber utf-8 - Codierung.
Karlo Smid
1
Repr- Codierungen strmit der speziellen string_escapeCodierung. Die Zeichenfolge war bereits als UTF-8 Unicode-codiert.
Zot
@KarloSmid: Was ich sagen wollte war , dass reprwahrscheinlich Schritte , um sicherzustellen , nimmt der Text kann durch ASCII dargestellt werden (mittels nicht-ASCII - Zeichen zu entkommen), nicht unbedingt , dass die Zeichenfolge wird als ASCII - codiert. Ich weiß immer noch nicht, ob das ganz richtig ist.
Hubro
All Python - Container (Liste, dict, Tupel, Set) umfasst dessen Inhalt als repr()Ausgang , wenn in einen String umgewandelt (nicht implementiert __str__, nur __repr__). Was Sie sehen, ist nichts Besonderes für UTF-8. Das repr()eines Strings gibt Ihnen gültige Python-String-Literale, die ASCII-sicher sind.
Martijn Pieters
2

Grundsätzlich war print in Python vor Python 3 eine spezielle Anweisung, die alle Zeichenfolgen druckte, wenn sie als Argumente angegeben wurden. Also print "foo","bar"einfach "print 'foo' gefolgt von 'bar'". Das Problem dabei war, dass es verlockend war, so zu tun, als wäre print eine Funktion, und die Python-Grammatik ist diesbezüglich nicht eindeutig, da (a,b)es sich um ein Tupel handelt, das eine Funktion von zwei Argumenten enthält aund bdiese foo(a,b)aufruft.

Daher haben sie die inkompatible Änderung für 3 vorgenommen, um Programme weniger mehrdeutig und regelmäßiger zu machen.

(Eigentlich denke ich, dass sich 2.7 wie 2.6 verhält, aber ich bin mir nicht sicher.)

Charlie Martin
quelle
Nein, es war nicht "verlockend", es als Funktion zu verwenden. :) Es war jedoch unmöglich, es als Funktion zu verwenden, so dass Sie beispielsweise nicht [x für x in alist drucken] ausführen können.
Lennart Regebro