¿Por qué el paréntesis impreso es voluntario en Python 2.7?

98

En Python 2.7, lo siguiente hará lo mismo

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

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

Sin embargo, lo siguiente no

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

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

En Python 3.x, el paréntesis printes obligatorio, lo que esencialmente lo convierte en una función, pero en 2.7 ambos funcionarán con resultados diferentes. ¿Qué más debo saber sobre printPython 2.7?

Hubro
fuente
7
En Python 2.x printes en realidad una declaración especial, no una función. Esta es también la razón por la que no se puede usar como: lambda x: print xTenga en cuenta que (expr)no crea una Tupla (da como resultado expr), pero lo ,hace.
Supongo que el soporte para imprimir como una función e imprimir como una declaración es para mantener la compatibilidad con versiones anteriores de Python al mismo tiempo que alienta a las personas a usar la nueva sintaxis para migrar hacia Python 3.
GWW
11
ps, para habilitar la función de impresión en 2.7 (y no tener el comportamiento de la declaración de impresión), debe hacer una importación futura:from __future__ import print_function
Jeff Mercado
¿El segundo ejemplo imprimirá de hecho "Hello, World!" (sin el espacio) o imprimirá "¡Hola, mundo!" (con el espacio) como en el ejemplo.
kapad

Respuestas:

106

En Python 2.x printes en realidad una declaración especial y no una función *.

Esta es también la razón por la que no se puede usar como: lambda x: print x

Tenga en cuenta que (expr)no crea una tupla (da como resultado expr), pero lo ,hace. Esto probablemente resulte en la confusión entre print (x)y print (x, y)en 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.]

Sin embargo, dado que printes una construcción de declaración / gramática de sintaxis especial en Python 2.x, entonces, sin el paréntesis, trata a los ,de una manera especial y no crea una Tupla. Este tratamiento especial de la printdeclaración le permite actuar de manera diferente si hay un seguimiento ,o no.

Codificación feliz.


* Este printcomportamiento en Python 2 se puede cambiar al de Python 3:

from __future__ import print_function
user2357112 es compatible con Monica
fuente
3
Gracias por la (expr) != tupleexplicación :-)
Hubro
5

Todo es muy simple y no tiene nada que ver con la compatibilidad hacia adelante o hacia atrás.

La forma general de la printdeclaración en todas las versiones de Python antes de la versión 3 es:

print expr1, expr2, ... exprn

(Cada expresión a su vez se evalúa, se convierte en una cadena y se muestra con un espacio entre ellas).

Pero recuerde que poner paréntesis alrededor de una expresión sigue siendo la misma expresión.

Entonces también puedes escribir esto como:

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

Esto no tiene nada que ver con llamar a una función.

Don O'Donnell
fuente
Esta es una respuesta perfectamente correcta, tampoco estoy seguro de por qué se rechazó tanto.
Martijn Pieters
No se trata de print (expr1), (expr2), ... (expr3), se trata de por qué print (expr1, expr2, ... , expr3)es legal en Python 2.x mientras que no debería estar de acuerdo con los estándares 2.x.
vinnief
5

Aquí tenemos un efecto secundario interesante cuando se trata de 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 última impresión es una tupla con valores de bytes hexadecimales.

Karlo Smid
fuente
7
Supongo que eso se debe a que print imprime UTF-8 correctamente, pero cuando recibe una tupla, como su última impresión, se ejecuta repren ella, en cuyo punto probablemente codifica todas las cadenas en el dictado en ASCII.
Hubro
3
@Codemonkey, tienes razón sobre repr . Te equivocas con ASCII. ASCII es la codificación predeterminada para Python. Pero tengo al comienzo del script de Python #encoding=utf-8, linux env LANG=en_US.UTF-8. Así que repr codifica no usando ASCII predeterminado, sino codificación utf-8.
Karlo Smid
1
Repr codifica strcon la string_escapecodificación especial . La cadena ya estaba codificada en Unicode como UTF-8.
tzot
@KarloSmid: Lo que quise decir es que reprprobablemente se toman medidas para garantizar que el texto se pueda representar mediante ASCII (mediante el escape de símbolos no ASCII), no necesariamente que la cadena esté codificada como ASCII. Sin embargo, todavía no sé si eso es completamente exacto.
Hubro
Todos los contenedores de Python (lista, dict, tupla, conjunto) incluyen su contenido como repr()salida cuando se convierten en una cadena (no implementan __str__, solo __repr__). Lo que ve no es especial para UTF-8; el repr()de una cadena le proporciona literales de cadena de Python válidos que son seguros para ASCII.
Martijn Pieters
2

Básicamente, en Python antes de Python 3, print era una declaración especial que imprimía todas las cadenas si se obtenían como argumentos. Así que print "foo","bar"simplemente significa "imprimir 'foo' seguido de 'barra'". El problema con eso era que era tentador actuar como si print fuera una función, y la gramática de Python es ambigua en eso, ya que (a,b)es una tupla que contiene ay bpero foo(a,b)es una llamada a una función de dos argumentos.

Así que hicieron el cambio incompatible de 3 para que los programas fueran menos ambiguos y más regulares.

(En realidad, creo que 2.7 se comporta como 2.6 en esto, pero no estoy seguro).

Charlie martin
fuente
No, no fue "tentador" usarlo como una función. :) Sin embargo, era imposible usarlo como una función, por lo que no puede hacer [imprimir x por x en una lista] por ejemplo.
Lennart Regebro