2011-06-07 5 views
386

Al parecer, la siguiente es la sintaxis válida¿Qué hace el carácter 'b' delante de un literal de cadena?

my_string = b'The string' 

me gustaría saber:

  1. ¿Qué significa este personaje b delante de la cadena?
  2. ¿Cuáles son los efectos de usarlo?
  3. ¿Cuáles son las situaciones apropiadas para usarlo?

encontré una related question aquí en la SO, pero esa pregunta es acerca de PHP sin embargo, y se establece la b se utiliza para indicar la cadena es binaria, en lugar de Unicode, lo que era necesario para el código para que sea compatible desde la versión de PHP < 6, al migrar a PHP 6. No creo que esto se aplique a Python.

Encontré this documentation en el sitio de Python sobre el uso de un carácter u en la misma sintaxis para especificar una cadena como Unicode. Lamentablemente, no menciona el carácter b en ningún lugar de ese documento.

Además, solo por curiosidad, ¿hay más símbolos que b y u que hacen otras cosas?

Respuesta

211

Para citar the Python 2.x documentation:

Un prefijo de 'b' o 'B' se ignora en Python 2; indica que el literal debe convertirse en un literal de bytes en Python 3 (por ejemplo, cuando el código es convertido automáticamente con 2to3). Un prefijo 'u' o 'b' puede ir seguido del y un prefijo 'r'.

Los Python 3.3 documentation estados:

Bytes literales siempre tienen el prefijo 'b' o 'B'; producen una instancia del tipo de bytes en lugar del tipo str. Solo pueden contener caracteres ASCII; los bytes con un valor numérico de 128 o superior deben expresarse con escapes.

+4

Parece que Python

+2

@Gweebz - si realmente está escribiendo una cadena en una codificación particular en lugar de con escapes unicode (por ejemplo, b '\ xff \ xfe \ xe12' en lugar de '\ u32e1'). – detly

+0

Eso tiene sentido. Voy a marcar este como la respuesta aceptada, pero también hay otras buenas respuestas aquí. –

6

Se convierte en un bytes literal (o str en 2.x), y es válido para 2.6+.

El r prefijo hace que las barras invertidas para ser "interpretada" (no ignorados, y la diferencia hace materia).

+0

Esto suena mal de acuerdo con la documentación citada en la respuesta de Aix; el b se ignorará en la versión de Python que no sea 3. –

+2

Será un 'str' en 2.x de cualquier manera, por lo que podría decirse que se ignora. La distinción importa cuando importa 'unicode_literals' del módulo' __future__'. –

+0

Disculpa, no entendí tu declaración original. Tu respuesta es precisa en lo que dice. –

10

El b denota una cadena de bytes.

Los bytes son los datos reales. Las cadenas son una abstracción.

Si tenía un objeto de cadena de caracteres múltiples y tomaba un solo carácter, sería una cadena y podría tener más de 1 byte de tamaño según la codificación.

Si tomó 1 byte con una cadena de bytes, obtendría un valor de 8 bits de 0-255 y podría no representar un carácter completo si esos caracteres debido a la codificación fueran> 1 byte.

TBH Usaría cadenas a menos que tuviera algún motivo específico de bajo nivel para usar bytes.

351

Python 3.x hace una clara distinción entre los tipos:

  • str = '...' literales = una secuencia de caracteres Unicode (UTF-16 o UTF-32, dependiendo de cómo se compiló Python)
  • bytes = b'...' literales = una secuencia de octetos (números enteros entre 0 y 255)

Si está familiarizado con Java o C#, piensan en str como String y bytes como byte[]. Si está familiarizado con SQL, piense en str como NVARCHAR y bytes como BINARY o BLOB. Si está familiarizado con el registro de Windows, piense en str como REG_SZ y bytes como REG_BINARY. Si está familiarizado con C (++), entonces olvide todo lo que ha aprendido sobre char y cadenas, porque UN CARÁCTER NO ES BYTE. Esa idea es obsoleta por mucho tiempo.

Utiliza str cuando quiere representar texto.

print('שלום עולם') 

Se utilizan bytes cuando se quiere representar datos binarios de bajo nivel como estructuras.

NaN = struct.unpack('>d', b'\xff\xf8\x00\x00\x00\x00\x00\x00')[0] 

Puede encode un str a un objeto bytes.

>>> '\uFEFF'.encode('UTF-8') 
b'\xef\xbb\xbf' 

Y se puede decodificar un bytes en un str.

>>> b'\xE2\x82\xAC'.decode('UTF-8') 
'€' 

Pero no puede mezclar libremente los dos tipos.

>>> b'\xEF\xBB\xBF' + 'Text with a UTF-8 BOM' 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: can't concat bytes to str 

La notación b'...' es algo confuso ya que permite que los bytes 0x01-0x7F a ser especificado con caracteres ASCII en lugar de números hexadecimales.

>>> b'A' == b'\x41' 
True 

Pero debo destacar, un personaje no es un byte.

>>> 'A' == b'A' 
False 

En Python 2.x

Pre-3.0 versiones de Python carecían de este tipo de distinción entre el texto y datos binarios.En cambio, hubo:

  • unicode = u'...' literales = secuencia de caracteres Unicode = 3.x str
  • str = '...' literales = secuencias de bytes enmascarados/caracteres
    • Por lo general, texto, codificado en algunos codificación no especificada.
    • Pero también se usa para representar datos binarios como struct.pack de salida.

Con el fin de facilitar la transición 2.x con 3.x, la sintaxis literal b'...' fue portado a Python 2.6, a fin de permitir distinguir cadenas binarias (que debe ser bytes en 3. x) desde cadenas de texto (que debe ser str en 3.x). El prefijo b no hace nada en 2.x, pero le dice al script 2to3 que no lo convierta en una cadena Unicode en 3.x.

Así que sí, b'...' literales en Python tienen el mismo propósito que lo hacen en PHP.

Además, sólo por curiosidad, ¿hay símbolos más que el B y T que hacen otras cosas ?

El r prefijo crea una cadena de texto (por ejemplo, r'\t' es una barra invertida + t en lugar de una pestaña) y triples comillas '''...''' o """...""" permiten literales de cadena multilínea.

+9

+1 ¡Gracias por su minuciosa respuesta! Habría marcado esto como correcto ayer antes de que Aix me proporcione suficiente información para considerar su respuesta como la primera correcta. –

+1

Gracias! Lo entendí después de leer estas oraciones: "Con el fin de facilitar la transición 2.x-a-3.x, la sintaxis literal b '...' se transfirió a Python 2.6, para permitir distinguir cadenas binarias (que deberían ser bytes en 3.x) de cadenas de texto (que debe ser str en 3.x). El prefijo b no hace nada en 2.x, pero le dice al script 2to3 que no lo convierta en una cadena Unicode en 3.x. –

+0

explicación de la información de la versión python fue muy útil. Gracias. –

6

He aquí un ejemplo donde la ausencia de 'b' sería lanzar una excepción TypeError en Python 3.x

>>> f=open("new", "wb") 
>>> f.write("Hello Python!") 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: 'str' does not support the buffer interface 

Adición de un prefijo 'b' sería solucionar el problema.

+1

comentario útil fella, gracias del futuro –

0

Además de lo que otros han dicho, tenga en cuenta que un solo carácter en Unicode puede constar de múltiples bytes.

La manera en que funciona Unicode es que tomó el formato ASCII antiguo (código de 7 bits que se parece a 0xxx xxxx) y multi-bytes sequences donde todos los bytes comienzan con 1 (1xxx xxxx) para representar caracteres más allá de ASCII para que Unicode sea backwards-compatible con ASCII.

>>> len('Öl') # German word for 'oil' with 2 characters 
2 
>>> 'Öl'.encode('UTF-8') # convert str to bytes 
b'\xc3\x96l' 
>>> len('Öl'.encode('UTF-8')) # 3 bytes encode 2 characters ! 
3 
Cuestiones relacionadas