2009-11-15 9 views
11

La presentación de Guido van Rossum sobre Python 3000 menciona varias cosas para hacer más fácil una transición de Python 2 a Python 3. Habla específicamente sobre el manejo de texto desde el cambio a Unicode ya que la única representación de cadenas en Python 3 es uno de los principales cambios.Python: datos frente a texto?

En cuanto a la manipulación de texto va, una diapositiva (# 14) dice:

  • En 2.6:
    • Use bytes y b '...' para todos los datos (Conociendo estos son sólo un alias para una str y '...')
    • utilizar unicode y u '...' para todo el texto
  • En 2.5:
    • '...' para datos, u ... '' el texto

que estoy usando Python 2.6.4. ¿Qué significa esto exactamente para mí?

En el mundo de Python, ¿cuál es la diferencia entre datos y texto?

Respuesta

17

En pocas palabras, la forma en que se manejan el texto y los datos en Py3k podría ser el cambio más "definitivo" en el idioma. Al conocer y evitar, cuando sea posible, las situaciones en las que la lógica de Python 2.6 funcionará de forma diferente que en 3.x, podemos facilitar la migración cuando sucede. Sin embargo, debemos esperar que algunas partes de la lógica 2.6 pueden requerir atención y modificaciones especiales, por ejemplo, para hacer frente a las codificaciones distintas etc.

La idea detrás de la sugerencia de BDFL en la diapositiva 14 es, probablemente, para empezar "usando" los mismos tipos que Py3k admite (y solo estos), a saber, cadenas de caracteres unicode para cadenas (tipo str) y secuencias de bytes de 8 bits para "datos" (tipo bytes).

El término "usando" en la frase anterior se usa bastante poco porque la semántica y el almacenamiento/codificación asociados para estos tipos difieren entre las versiones 2.6 y 3.x. En Python 2.6, el tipo de bytes y la sintaxis literal asociada (b'xyz ') simplemente se asignan al tipo str. Por lo tanto

# in Py2.6 
>>'mykey' == b'mykey' 
True 
b'mykey'.__class__ 
<class 'str'> 

# in Py3k 
>>>'mykey' == b'mykey' 
False 
b'mykey'.__class__ 
<class 'bytes'> 

Para responder a su pregunta [en los comentarios a continuación], en 2,6 si se utiliza b'xyz' o 'xyz', Python lo entiende como el mismo y una cosa: un str. Lo que es importante es que que entender esto como [potencialmente/en-el-futuro] dos tipos distintos con un propósito distinto:

  • str para obtener información de texto similares, y
  • bytes para las secuencias de de octetos que almacenan los datos a mano.

Por ejemplo, nuevamente hablando cerca de su ejemplo/pregunta, en Py3k podrá tener un diccionario con dos elementos que tienen teclas similares, una con b'mykey 'y la otra con' mykey ', sin embargo, bajo 2.6 esto no es posible, ya que estas dos claves son realmente iguales; lo que importa es que conozca este tipo de cosas y evite (o marque explícitamente de forma especial en el código) las situaciones en las que el código 2.6 no funcionará en 3.x.

En Py3k, str es una cadena abstracta de Unicode, una secuencia de puntos de código Unicode (caracteres) y Python trata de convertir esto a/desde su forma codificada cualquiera que sea la codificación (como programador puedes opinar sobre la codificación pero en el momento en que se ocupa de las operaciones de cadena y tal no necesita preocuparse por estos detalles). Por el contrario, bytes es una secuencia de "cosas" de 8 bits que la semántica y la codificación se dejan totalmente al programador.

Así, a pesar de que Python 2.6 no ve una diferencia, utilizando explícitamente bytes()/b '...' o str()/u '...', que ...

  • ... prepararse y preparar a su programa para los próximos tipos y semántica de Py3k
  • ... hacen que sea más fácil para la conversión automática (herramienta 2to3 u otro) del código fuente, por lo que el b en B'. .. 'se mantendrá y el u de u' ... 'se eliminará (ya que el único tipo de cadena será unicode).

Para obtener más información:
Python 2.6 What's new (ver PEP 3112 Bytes literales)
Python 3.0 What's New (ver Text Vs. Data Instead Of Unicode Vs. 8-bit cerca de la parte superior)

+2

También es una buena práctica para hacer que realmente piensa acerca de si nos referimos a una cadena de caracteres o una cadena de bytes! El único problema es, por supuesto, que pierde compatibilidad con Python 2.5 y versiones anteriores. – bobince

+0

entiendo por qué * * que es una buena idea hacer esto, pero todavía no estoy claro en cuanto a cómo * * exactamente. A menos que una función espere explícitamente una cadena de bytes, ¿cuándo uso una cadena de bytes frente a una cadena de caracteres? my_dict [b'mykey '] o my_dict [u'mykey']? ¿Cuándo se consideran datos, cuándo se considera texto? – cschol

+0

Gracias por la actualización detallada. – cschol

2

La respuesta a la primera pregunta es sencilla: En Python 2.6 se puede ¿has estado acostumbrado? Pero, si lo desea, puede cambiar a las normas Py3k escribiendo:

from __future__ import unicode_literals 

Su segunda pregunta necesita más aclaraciones:

Las cadenas son datos que se imprimen como caracteres humanos. No solo en Python, sino que cada idioma (lo sé) tiene su camino cuando se trata de cadenas.

Sin embargo, los motivos comunes son codificaciones. Las codificaciones son la forma de mapear secuencias de bytes a glifos (es decir, símbolos en su mayoría imprimibles).

Python ofrece una forma simple de superar las complejidades de la gestión de codificaciones (cuando se colocan literales de cadena en el código).

Veamos un ejemplo muy sencillo:

>>> len("Mañana") 
7 

sólo veo 6 símbolos. Así que espero que len haya regresado 6. ¿De dónde viene este "símbolo" extra? Bueno en UTF-8 el símbolo ñ se representa con 2 bytes. Antes de Py3k, los literales de cadena son solo secuencias de bytes. Entonces, Python ve esa cadena como bytes y los cuenta a todos: Ma\xc3\xb1ana.

Sin embargo, si ejecuta la siguiente:

>>> len(u"Mañana") 
6 

Así Python "sabe" exactamente que las secuencias de 2 bytes para "n" es para ser considerado como una sola letra.

Esto de ninguna manera es exclusivo de Python.La siguiente secuencia de comandos PHP muestra el mismo comportamiento:

[email protected]:~$ php <<EOF 
<?php 
echo strlen("Mañana")."\n"; 
?> 
EOF 
7 

sucede La solución PHP para ser más elaborado:

[email protected]:~$ php <<EOF 
<?php 
echo mb_strlen("Mañana", "utf-8")."\n"; 
?> 
EOF 
6 

Aviso tengo que sustituir mb_strlen para strlen y tengo que pasar utf-8 (la codificación) como un segundo argumento

Una palabra de advertencia: Las cadenas de usuario proporcionado vienen generalmente como bytes, no cadenas Unicode. Entonces debes ocuparte de eso. Ver más en http://mail.python.org/pipermail/python-list/2008-July/139193.html

+3

"codificaciones son el camino para mapear secuencias de bytes a glifos (es decir símbolos mayoría imprimibles)". Eso no es del todo correcto. Son asignaciones de secuencias de bytes a * caracteres *, independientemente de que se impriman o no. Asignar caracteres a glifos es otro proceso completamente dependiente del sistema de fuentes. – quark

+0

@quark. Estoy de acuerdo. Estaba tratando de simplificar el discurso de la respuesta, que es bastante grande. – manu

Cuestiones relacionadas