Pourquoi les parenthèses imprimées sont-elles volontaires dans Python 2.7?

98

Dans Python 2.7, les deux éléments suivants feront la même chose

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

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

Cependant, ce qui suit ne sera pas

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

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

En Python 3.x, les parenthèses printsont obligatoires, ce qui en fait essentiellement une fonction, mais dans 2.7 les deux fonctionneront avec des résultats différents. Que dois-je savoir d'autre sur printPython 2.7?

Hubro
la source
7
En Python 2.x printest en fait une instruction spéciale, pas une fonction. C'est aussi pourquoi il ne peut pas être utilisé comme: lambda x: print xNotez que (expr)cela ne crée pas de Tuple (il en résulte expr), mais le ,fait.
Je suppose que la prise en charge de l'impression en tant que fonction et de l'impression en tant qu'instruction vise à maintenir la compatibilité ascendante avec les anciennes versions de python tout en encourageant les gens à utiliser la nouvelle syntaxe pour migrer vers python 3.
GWW
11
ps, Pour activer la fonction d'impression dans 2.7 (et ne pas avoir le comportement de l'instruction d'impression), vous devez faire une importation future:from __future__ import print_function
Jeff Mercado
Le deuxième exemple affichera-t-il en fait "Hello, World!" (sans l'espace) ou imprimera-t-il "Hello, World!" (avec l'espace) comme dans l'exemple.
kapad

Réponses:

107

En Python 2.x printest en fait une instruction spéciale et non une fonction *.

C'est aussi pourquoi il ne peut pas être utilisé comme: lambda x: print x

Notez que (expr)cela ne crée pas de Tuple (il en résulte expr), mais le ,fait. Cela entraîne probablement la confusion entre print (x)et print (x, y)dans 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.]

Cependant, comme il prints'agit d'une instruction de syntaxe / construction grammaticale spéciale en Python 2.x, sans les parenthèses, il traite les ,'s d'une manière spéciale - et ne crée pas de tuple. Ce traitement particulier de l' printinstruction lui permet d'agir différemment s'il y a un suivi ,ou non.

Bon codage.


* Ce printcomportement dans Python 2 peut être changé pour celui de Python 3:

from __future__ import print_function
user2357112 prend en charge Monica
la source
3
Merci pour l' (expr) != tupleexplication :-)
Hubro
5

Tout cela est très simple et n'a rien à voir avec la compatibilité ascendante ou descendante.

La forme générale de l' printinstruction dans toutes les versions de Python avant la version 3 est:

print expr1, expr2, ... exprn

(Chaque expression est à son tour évaluée, convertie en chaîne et affichée avec un espace entre elles.)

Mais rappelez-vous que placer des parenthèses autour d'une expression est toujours la même expression.

Vous pouvez donc également écrire ceci comme suit:

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

Cela n'a rien à voir avec l'appel d'une fonction.

Don O'Donnell
la source
C'est une réponse parfaitement correcte, je ne sais pas non plus pourquoi elle a été aussi défavorisée.
Martijn Pieters
Il ne s'agit pas print (expr1), (expr2), ... (expr3), il s'agit de savoir pourquoi print (expr1, expr2, ... , expr3)est légal en python 2.x alors que cela ne devrait pas être conforme aux normes 2.x.
vinnief
5

Ici, nous avons un effet secondaire intéressant en ce qui concerne UTF-8.

>> 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')

La dernière impression est un tuple avec des valeurs d'octets hexadécimaux.

Karlo Smid
la source
7
Je suppose que c'est parce que print imprime correctement UTF-8, mais quand il reçoit un tuple, comme votre dernière impression, il s'exécute reprdessus, auquel point il encode probablement toutes les chaînes du dict en ASCII.
Hubro
3
@Codemonkey, vous avez raison à propos de repr . Vous vous trompez sur ASCII. ASCII est l'encodage par défaut pour Python. Mais j'ai au début du script Python #encoding=utf-8, linux env LANG=en_US.UTF-8. Donc repr encode sans utiliser l'ASCII par défaut, mais avec l'encodage utf-8.
Karlo Smid
1
Repr encode stravec le string_escapecodage spécial . La chaîne était déjà codée en Unicode en UTF-8.
tzot
@KarloSmid: Ce que je voulais dire, c'est que cela reprprend probablement des mesures pour s'assurer que le texte peut être représenté par ASCII (au moyen d'échappements de symboles non ASCII), pas nécessairement que la chaîne soit codée en ASCII. Je ne sais toujours pas si c'est tout à fait exact.
Hubro
Tous les conteneurs Python (liste, dict, tuple, ensemble) incluent leur contenu en repr()sortie lorsqu'ils sont convertis en chaîne (ils ne sont pas implémentés __str__, uniquement __repr__). Ce que vous voyez n'est pas spécial pour UTF-8; le repr()of a string vous donne des littéraux de chaîne Python valides qui sont ASCII-safe.
Martijn Pieters
2

Fondamentalement, dans Python avant Python 3, print était une instruction spéciale qui imprimait toutes les chaînes si elles étaient obtenues en arguments. Donc print "foo","bar"simplement signifiait "imprimer 'foo' suivi de 'bar'". Le problème avec cela était qu'il était tentant d'agir comme si print était une fonction, et la grammaire Python est ambiguë à ce sujet, car (a,b)est un tuple contenant aet bmais foo(a,b)est un appel à une fonction de deux arguments.

Ils ont donc fait le changement incompatible pour 3 pour rendre les programmes moins ambigus et plus réguliers.

(En fait, je pense que 2.7 se comporte comme 2.6 à ce sujet, mais je ne suis pas certain.)

Charlie Martin
la source
Non, ce n'était pas «tentant» de l'utiliser comme une fonction. :) Cependant, il était impossible de l'utiliser comme fonction, donc vous ne pouvez pas faire [print x for x in alist] par exemple.
Lennart Regebro