Python 3: pequeños cambios misceláneos

sábado, 6 de diciembre de 2008
El operador <>
No existe más, debería usarse != en su lugar (más de una manera de hacer lo mismo!)

El operador !=
Por defecto devolverá lo opuesto de ==, a menos que este último lance NotImplementedError. Este comportamiento es esperable y por tanto su ausencia era una fuente de bugs. En su momento reporté un bug en el ORM de Django por esta precisa razón.

print es una función
Anteriormente, print era un statement: una palabra reservada del lenguaje con tratamiento especial (como es el caso de if o class). En Python 3 print pasa a ser una función convencional. Esto es consistente con el hecho de que no hay ninguna razón para que no lo sea! Si bien va a ser necesario agregar paréntesis que antes no hacían falta, también va a ser posible utilizar print como antes era imposible.
# Python 2.x
print "hola mundo"    # imprime y va a la línea
print "hola mundo",   # imprime y no va a la línea
map(print, [1,2,3,4]) # error!

# Python 3.x
print("hola mundo")
print("hola mundo", end="")
map(print, [1,2,3,4]) # ok!
La mayoría de la sintaxis especial (y muchas veces extraña) de print ahora se reemplaza con keywords para la función. Hay más información en la página de cambios en Python 3 y en la documentación.

La división anda bien
El histórico problema de que la división de enteros da entero en Python se eliminó de una buena vez. Esto era un problema clásico al comenzar a programar, y forzaba a castear a float en muchas ocasiones para asegurarse de que al menos uno de los dos argumentos de la división sea float (en ese caso la división puede devolver float).
uno = 1
dos = 2

# Python 2.x
a = uno / dos
b = uno // dos
c = float(uno) / 2
print a # imprime 1
print b # imprime 1
print c # imprime 0.5

# Python 3.x
a = uno / dos
b = uno // dos
c = float(uno) / 2
print(a) # imprime 0.5 :D
print(b) # imprime 1
print(c) # imprime 0.5
Unificación de Int y Long
En Python 2 existían las dos clases de enteros, y si bien interoperaban entre ellas perfectamente, al imprimir un entero largo por pantalla se imprimía una curiosa L al final.
>>> import sys
>>> sys.maxint
2147483647
>>> sys.maxint + 1
2147483648L # <- "L" al final
>>> type(sys.maxint).__name__
'int'
>>> type(sys.maxint+1).__name__
'long'
Como la constante sys.maxint quedó por lo tanto sin uso, fue eliminada también.

reduce() no es más builtin
En Python 1.0 (allá por 1994) se agregaron varias primitivas de programación funcional: map, filter, reduce. Estas primitivas permiten, usando una única llamada, reescribir varios bucles simples que se suelen utilizar al programar.

Si bien map y filter quedan casi sin cambios en Python 3, reduce se eliminó porque produce código difícil de leer y por lo tanto es más conveniente utilizar un ciclo en lugar de la función. Para los que deseen seguirla utilizando, reduce ahora vive en el módulo functools.

Hace un tiempo expliqué map, filter y reduce en el foro de PC++.

Volaron muchos otros builtins
Todos los siguientes builtins volaron. Los idioms que los reemplazan están disponibles en la documentación sobre cambios en Python 3.
  • apply
  • callable
  • coerce
  • reload
  • file
  • y varios más!

9 comentarios:

Pablo Antonio dijo...

Lo de print (ahora como función), más allá de que hay que escribir un poco más, parece más prolijo y está bueno que se hayan transformado algunas keywords en parámetros de la función.

Lo del cambio de comportamiento de la barra de división tiene sentido.

Lo de los builtins; varios de ellos no los había utilizado nunca así que no me afecta demasiado :)

Gracias por tomarte el tiempo de mostrar las cosas nuevas de Python 3K para los que no tuvimos tiempo (todavía) de ponernos a chusmear sobre eso.

GomoX dijo...

Hola Pablo, gracias por tu comentario. Estoy escribiendo varios posts más sobre otros cambios más significativos también. En general creo que todas las modificaciones que se hicieron son 100% positivas.

Cristian Q dijo...

Hola Gonzalo, hace instantes me aclaraste este tema en PC++ y te lo agradezco. Me estaba martirizando lo de print ya que soy nuevo en Python y no sabia de estos cambios!!
Gracias nuevamente.

Rodolfo Ochoa dijo...

tiene cosas buenas, pero tambien malas, esta nueva version, dejo mucha documentación, tutoriales y libros obsoleta, ademas de que es más lenta.

Gxus dijo...

¿es mas lenta la version 3 que las anteriores?
Si es asi, ¿en que medida?

GomoX dijo...

Cuando salió Python 3.0 todo el stack de acceso a archivos se había reescrito en Python para simplificarlo y remodelarlo, con lo cual tenía un bache de performance severo en temas de I/O respecto de Python 2.6. En Python 3.1 se portó a C el nuevo stack con lo cual la diferencia de rendimiento entre Python 2 y 3 se redujo significativamente.

Hoy por hoy Python 3 es marginalmente más lento que Python 2.6 en algunas cuestiones, y más rápido en otras, pero la diferencia es suficientemente pequeña como para que la decisión de usar uno u otro no pase por la velocidad.

Más información:
http://www.rmi.net/~lutz/python31-speed-tests.html

Alejandro J. Alvarez S. dijo...

Me ha gustado mucho tu artículo. Has aclarado muchas de mis dudas, y lo de la división, gracias a Dios lo arreglaron xD

Excelente post ... y tienes un nuevo seguidor :-)

°.::abi.gfx::.° dijo...

Muchas gracias, la verdad es que no sabia porque no me funcionaba el print en 3.x y las otras variables.

saludos

Sebas dijo...

Gracias por la info, recien estoy empezando con esto de python y me acabo de dar cuenta que en casa instalé la version 3.X y en el work la 2.x... no entendía porque en casa me daba error de sintaxis, ahora ya lo sé \(^.^)/
Saludos

Publicar un comentario