Uso del intern (RE: Asignaciones e identidades)
Hernan Martinez Foffani
hernan en orgmf.com.ar
Mar Ago 20 11:16:38 CEST 2002
Chema:
> [fui yo, Hernan, no Attila ;-)]:
> > el programador puede forzar el interning de strings mediante el
> > builting intern()
>
> Entiendo que todo se trate de una "optimización" del intérprete,
> aunque no llego a ver claras cuáles son las ventajas.
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.
> .... En el capítulo de
> python avanzado comentan que para comparar dos cadenas es más
> rápido combinar 'intern()' e 'is' que el operador de comparación
> '==' entre cadenas. Esto es, en lugar de:
>
> # En lugar de
> "mi variable" == "mi var" + "riable"
>
> # más rápido
> intern("mi variable") is intern("mi va" + "riable")
>
> Desde luego sólo notaríamos la velocidad si tuviéramos que
> comparar numerosas cadenas.
interesante.... esto no lo sabia.
probablemente esta sea una de las razones por la cual se expuso
intern() y no quedó solo como un detalle de implementacion del
interprete.
[la clase String de Java tiene tambien un metodo .intern() que
hace lo mismo.]
> Entiendo, pues, que la rapidez no es otra cosa que aprovecharse
> de que el intérprete ya había hecho la "comparación"
> implícitamente cuando creó y dio la misma representación interna
> a las cadenas que queremos comparar. Pero sigo sin comprender
> porqué en el ejemplo:
>
> >>> a = "mi variable"
> >>> b = "mi variable"
> >>> a is b
> 0
> >>> intern(a) is intern(b)
> 1
>
> Si ambas cadenas comparten la misma representación interna, ¿por
> qué no son el mismo objeto?
en el caso "mi variable" no se hace intern automatico porque la
cadena tiene un blanco en el medio. para que se "interne" hay que
llamar al builtin en forma explicita.
>>> x = "me voy a internar"
>>> id(x)
10266200 <<-- x es un nuevo objeto
>>> xi = intern(x)
>>> id(xi)
10266200 <<-- el objeto x se interna
>>> y = "me voy a internar"
>>> id(y)
10343536 <<-- y es un nuevo objeto
>>> yi = intern(y)
>>> id(yi)
10266200 <<-- intern() devuelve la referencia a
>>> x internado
>>> id(y)
10343536 <<-- pero el nombre y sigue apuntando al
>>> objeto original.
intern() no puede cambiar el binding del nombre "y" del objeto
original id:10343536 al objeto internado id:10266200 porque
para ello tendría que modificar el espacio de nombres del que
la invoco.
Saludos,
-Hernan
Más información sobre la lista de distribución Python-es