
- El tipo de datos dict dispone ahora de un mecanismo que le permite proporcionar valores por defecto en caso de que la clave indicada no se encuentre en el diccionario. En esos casos, se devuelve el resultado de llamar al método del diccionario __missing__(key), si está definido. Este mismo mecanismo es el usado para implementar la nueva clase defaultdict en el módulo dictionary. El siguiente código muestra un ejemplo de diccionario que devuelve cero siempre que se accede a una clave inexistente:
class zerodict (dict):
def __missing__ (self, key):
return 0
d = zerodict({1:1, 2:2})
print d[1], d[2] # Prints 1, 2
print d[3], d[4] # Prints 0, 0 - Las cadenas de texto, ya sean las convencionales de 8 bits o las unicode, disponen ahora de los métodos partition(sep) y rpartition(sep).
A menudo se usa el método find() para obtener un índice que es usado posteriormente para dividir una cadena de texto en dos partes, antes y después del separador. El método partition condensa este patrón en una sola llamada. El método partition(sep) divide la cadena de texto por la primera ocurrencia de sep, y retorna una tripleta (una tupla de tres elementos) conteniendo el texto antes del separador, el separador y el resto del texto hasta el final de la cadena. En caso de no encontrarse el separador, devuelve una tripleta con la cadena de texto completa en la primera posición, y cadenas vacías en la segunda y tercera posición. El método rpartition(sep) hace lo mismo, pero usando la última ocurrencia de sep, en vez de la primera (La r de rpartition viene de reverse).
Veamos algunos ejemplos:
>>> ('http://www.python.org').partition('://')
('http', '://', 'www.python.org')
>>> ('file:/usr/share/doc/index.html').partition('://')
('file:/usr/share/doc/index.html', '', '')
>>> (u'Subject: a quick question').partition(':')
(u'Subject', u':', u' a quick question')
>>> 'www.python.org'.rpartition('.')
('www.python', '.', 'org')
>>> 'www.python.org'.rpartition(':')
('', '', 'www.python.org')
Esta implementación ha sido desarrollada por Fredrik Lundh gracias a una sugerencia de Raymond Hettinger. - Siguiendo con las cadenas de texto, los métodos startswith() y endswith() aceptan ahora tuplas de cadenas como parámetro, lo que permite buscar por varios valores a la vez. Veamos un ejemplo:
def is_image_file (filename):
return filename.endswith(('.gif', '.jpg', '.tiff'))
Implementado por Georg Brandl y sugerido por Tom Lynn. - Las funciones predefinidas min() y max() obtienen un parámetro opcional, análogo al parámetro key de la función sort(). Mediante este parámetro se puede indicar una función, que acepta un único parámetro, y que es llamada para cada valor de lo lista. La función min()/max() devolverá aquel elemento cuyo valor retornado por la función para dicho elemento sea mínimo/máximo. Por ejemplo, para encontrar la cadena de texto más larga en una lista, se podría hacer lo siguiente:
>>> L = ['media', 'larga cual longaniza', 'pequeña']
>>> print max(L) # Imprime "pequeña"
pequeña
>>> print max(L, key=len) # Imprime la frase más larga
larga cual longaniza
Esta funcionalidad es una contribución de Steven Bethard y Raymond Hettinger. - Hay dos nuevos funciones predefinidas: any() y all(), que evalúan la existencia de valores True en un iterador. La función any() retorna True si alguno de los valores retornados por el iterador es verdadero, en caso contrario retorna False. La función all() retorna True sólo si todos los valores retornados por el iterador son verdaderos. La implementación corrió a cargo de Raymond Hettinger, a partir de una sugerencia de Guido van Rossum.
- El resultado de llamar al método __hash__() de una clase puede ser ahora un entero normal o un entero grande. En este último caso, se toma como valor el hash del entero grande. En anteriores versiones era obligado usar enteros normales, pero en la nueva versión 2.5, la función predefinida id() ha sido cambiada para que siempre devuelva valores no negativos, y los usuarios a menudo usan id(self) en los métodos __hash__, aunque sea una práctica desaconsejada.
- La codificación por defecto de los módulos es ahora ASCII. Si un módulo usa cadenas de texto con caracteres de 8 bits, y no se ha incluido una declaración de codificación, se considera a partir de esta versión un error de sintaxis. En Python 2.4 esto se consideraba un aviso (warning) y no un error. En el PEP 262 se explica como declarar la codificación de un módulo. Por ejemplo, se puede añadir una línea como la siguiente:
# -*- coding: latin1 -*-
Como una de las primeras líneas de código del módulo. - Hay un nuevo warning, UnicodeWarning, que se dispara cada vez que se intenta comparar una cadena en unicode con otra de 8 bits, y esta última no puede ser convertida a unicode usando la codificación ASII por defecto. El resultado de la comparación es False.
Anteriormente, esto habría provocado una excepción de tipo UnicodeDecodeError, pero en 2.5 eso podría provocar un problema a la hora de acceder a un diccionario. Sin este cambio, si buscáramos en un diccionario por unichr(128), pero se usó chr(128) como clave, obtendríamos una excepción de tipo UnicodeDecodeError. Otros cambios en 2.5 condujeron a que esta excepción se elevara, en vez de ser suprimida, por el código en dictobject.c, la implementación de los diccionarios.
>>> chr(128) == unichr(128) # Can't convert chr(128) to Unicode
__main__:1: UnicodeWarning: Unicode equal comparison failed
to convert both arguments to Unicode - interpreting them
as being unequal
False
>>> chr(127) == unichr(127) # chr(127) can be converted
True
Elevar una excepción para estas comparaciones sería estrictamente correcto, pero el cambio habría provocado la ruptura de código ya existente, por lo que se ha preferido introducir el aviso UnicodeWarning.
la implementación corrió a cargo de Marc-André Lemburg. - Un error habitual que se comente al programa en Python es olvidar incluir el fichero __init__ en un directorio de paquetes de módulos. Detectar este error puede ser confuso, y normalmente implica ejecutar el intérprete con la opción -v para que muestre todos los directorios en los que se ha buscado. En Python 2.5, se dispara un nuevo aviso, ImportWarning , cuando se ha indicado un directorio como paquete pero no se ha encontrado el fichero __init__.py dentro de este. Este aviso se ignora por defecto; es necesario incluir la opción -Wd en la llamada al interprete para que se muestre. Implementación de Thomas Wouters.
- En una definición de clase, la lista de clases de las cuales deriva puede ser una lista vacía. Por ejemplo, el siguiente código es válido en python 2.5:
class C():
Implementado por Brett Cannon.
pass
Cambios en el interprete interactivo
- En el entorno interactivo, quit y exit han sido, desde hace bastante tiempo, cadenas de texto, de forma que los novatos obtienen un mensaje de ayuda cuando intentan salir del interprete:
>>> quit
'Use Ctrl-D (i.e. EOF) to exit.'
En Python 2.5, quit y exit son ahora objetos que siguen produciendo una representación de texto en forma de mensaje de ayuda, pero también son objetos llamables. El novato que intente ejecutar quit() o exit() conseguirá salir del interprete, como esperaba. Implementado por Georg Brandl. - El ejecutable de python acepta ahora las opciones en formato largo estándar --help y --version. Además, en Windows se puede usar la opción /? para mostrar un mensaje de ayuda. Implementado por Georg Brandl.
Optimizaciones
La mayoría de las optimizaciones fueron desarrolladas en el NeedForSpeed sprint, un evento que tuvo lugar en Reykjavik, Islandia, del 21 al 28 de mayo de 2006. En encuentro se centró en acelerar y optimizar la implementación de CPython, y fue financiada por EWT LLC y con ayuda local de CCP Games. Las optimizaciones fruto de este encuentro están indicadas en la siguiente lista:
- Cuando se incluyó en Python 2.4 el soporte para el tipo de datos set, se implementó usando el tipo de datos dict. En esta nueva versión, se ha reescrito toda la estructura de datos interna usada por los conjuntos, obteniéndose así una mejora en la velocidad en uso, a la vez que el consumo de memoria del diccionario se ha reducido a una tercera parte. Implementado por Raymond Hettinger.
- Se ha mejorado la velocidad de algunas operaciones realizadas en cadenas de texto unicode, como por ejemplo buscar subcadenas, particiones y codificación/decodificación de caracteres. Las mejoras en la búsqueda de subcadenas y en las particiones se las tenemos que agradecer a Fredrik Lundh y Andrew Dalke, que las implementaron en el NeedForSpeed sprint. La codificación de caracteres se la debemos a Walter Dörwald y Martin von Löwis.
- La función long(str, base) es ahora más rápida para grandes cadenas de texto, porque se realizan menos cálculos intermedios. El pico se obtienen para cifras entre 800 y 1000 dígitos, donde la función llega a ser 6 veces más rápida. Es un contribución de Alan McIntyre en el NeedForSpeed sprint.
- El módulo struct compila ahora las cadenas de texto de representación de formatos, y cachea los resultados, obteniendo así una mejora del 20% en la ejecución del código. Es una contribución de Bob Ippolito en el NeedForSpeed sprint.
- El módulo de expresiones regulares re ha acelerado su rendimiento entre un 1 y un 2%, al pasar a usar las funcionas de gestión de memoria de Python, en vez de las llamadas al sistema malloc() y free(). Contribución de Jack Diederich en el NeedForSpeed sprint.
- El optimizador de codigo de tipo mirilla (peephole optimizer) puede realizar ahora algunas agrupaciones sencillas en las expresiones. Por ejemplo, si escribimos algo como
a=2+3
, el generador de código realizará la suma y producirá código equivalente aa=5
. Esta mejora fue propuesta e implementada por Raymond Hettinger. - Las llamadas a funciones son ahora más rápidas, porque los objetos de tipo código ahora mantienen al frame terminado más recientemente en un campo interno (zombie frame), de forma que puede ser reutilizarlo la siguiente vez que el código es llamado. El parche original es de Michael Hudson, posteriormente modificado por Armin Rigo y Richard Jones. Es otra aportación lograda en el NeedForSpeed sprint.
Los objetos de tipo Frame son también un poco más pequeños, lo que puede mejorar las localizaciones en la caché y reducir ligeramente el consumo de memoria. Es una contribución de Neal Norwitz. - Las excepciones predefinidas de Python son ahora clases al nuevo estilo, un cambio que acelera considerablemente la instanciación de objetos. Gracias a estas mejoras, la gestión de excepciones es aproximadamente un 30% más rápida que en la versión 2.4. Es una contribución de Richard Jones, Georg Brandl y Sean Reifschneider en el NeedForSpeed sprint.
- Las importaciones recuerdan ahora las rutas intentadas, registrando la existencia o inexistencia de las mismas; esto acelera el arranque ya que el intérprete realiza menos llamadas a las funciones open() y stat(). Es una contribución de Martin von Löwis y Georg Brandl.
Ver comentarios