[Python-es] RE: Uso del intern (Parte 2)
Chema Cortes
chemacortes en wanadoo.es
Mie Ago 21 10:58:35 CEST 2002
Hernan dijo(sorry por el error en el mensaje anterior O:-)=
> el interning automatico (el que se activa sin llamar al builtin)
> lo hace el interprete en cadenas que tienen la forma
> "[A-Za-z_][[A-Za-z0-9_]*", o sea, cadenas que se parecen a
> nombres de validos en Python, y en los enteros de 0 a 99 inclusive.
>
> en los strings la optimización del intérprete es para el parser:
> las comparaciones de los nombres de objetos se hacen por
> identidad. en el caso de los enteros la optimización es en
> ejecución.
> en cuanto a la ganancia, no tengo idea.
Tal como "amenazé", me entro la locura y me metí con el código C del python. Lo primero que he observado es lo cuidadosos que son por controlar los malloc/free de memoria. Existe gran cantidad de código para depurar cualquier fallo que exista con fallos con la memoria.
Para evitar el realizar frecuentes llamadas a malloc/free que pudieran fragmentar la memoria, en las creaciones de objetos se puede reservar espacio (normalmente 1024 bytes) como buffer para almacenar unos cuantos objetos. A este buffer pueden ir a parar los que se usan más frecuentemente. Así tenemos que:
- enteros: se consideran que los enteros más frecuentes son desde el -1 al 99. Siempre que creemos un 'int' de este rango nos devolverá la misma referencia.
- reales (float): se reserva un buffer de 1024 bytes para objetos float, aunque no se comprueba antes de crearse el objeto si ya existía el mismo número en el buffer. Puedo suponer que para cálculo numérico intensivo se podría mejorar el rendimiento de python aumentando este buffer y recompilando.
- strings y unicodes: se "cachea" la cadena vacía "" y las cadenas de longitud de un caracter (más adelante comento un poco lo del 'intern')
- tuplas: sólo se "cachea" la tupla vacía (). Es curiosa la optimización que han usado aquí. Las tuplas de tamaño comprendido entre 0 y 20 comparten la misma estructura en memoria, variando tan sólo el valor que tiene cada una.
Con las tuplas sólo obtemos la misma referencia cuando se trata con la tupla vacía:
>>> a=(1,)
>>> b=(1,)
>>> a is b
0
>>> a=()
>>> b=()
>>> a is b
1
En cuanto a explicar lo de la "internalización automática" de strings tan sólo he comprobado que no se hace durante la creación del objeto string. Por lo tanto debe ser una consecuencia del "parser" y de cómo crea éste la tabla de símbolos que comparte con el compilador de bytecode. Parece ser que el parser que considerar a las cadenas simples como si fueran un símbolo más:
>>> a="Hola"
>>> a is intern("Hola")
1
>>> b="Hola y adiós"
>>> b is intern("Hola y adiós")
0
Quién sabe si en algún momento se le pasó por la cabeza a alguien que en python fuera válido hacer algo tal que así:
>>> $"MiVar"=1
Lo anterior no existe en python (todavía), pero algo similar sí que se puede ver en php:
$var="MiVar"
$$var=1
((En python se usaría para esto el 'eval'))
Saludos,
--
Chema Cortes (chemacortes en wanadoo.es)
_____________________________________________________________________
Horas ilimitadas para leer y enviar correos con Tarifa Plana Wanadoo
¡¡ desde las 3 de la tarde!!
Compruébalo en http://www.wanadoo.es/acceso-internet
Más información sobre la lista de distribución Python-es