Los prefijos que se anteponen ante un literal determinan el tipo del literal y cómo el intérprete lo trata al generarlo.
Literales de cadena formateados
Se especifican anteponiendo una "f" de "format" delante del literal, f""
, lo que indica que se trata de literales de cadena "formateados".
Se introdujeron por primera vez en Python 3.6 a partir de PEP 498 -- Literal String Interpolation y vienen a completar las otras formas ya existentes de formateo de cadenas que existen en Python:
El viejo estilo heredado de C usando %
:
>>> "%.2f %s %.2f = %.2f" % (7, "/", 3, 7/3)
'7.00 / 3.00 = 2.33'
>>> '%10s' % ('Hola',)
' Hola'
Método de las cadenas str.format()
y str.format_map
, builtin format()
.
>>> "{:.2f} {} {:.2f} = {:.2f}".format(7, "/", 3, 7/3)
'7.00 / 3.00 = 2.33'
>>> '{:>10}'.format('Hola')
' Hola'
>>> "{num1:.2f} {operador} {num2:.2f} = {resultado:.2f}".format(
num1=7, operador="/", num2=3, resultado=7/3
)
'7.00 / 3.00 = 2.33'
>>> "{num1:.2f} {operador} {num2:.2f} = {resultado:.2f}".format_map(
{"num1": 7, "operador": "/", "num2": 3, "resultado": 7/3}
)
'7.00 / 3.00 = 2.33'
>>> format(255, "02X")
'FF'
Los f"" strings siguen la misma sintaxis que str.format
:
En esencia las parejas de llaves {}
delimitan una diana de reemplazo. El código encerrado en las llaves es evaluado como código Python al procesar el literal y el resultado de la evaluación se usa para reemplazar todo los que hay dentro de las llaves, llaves incluidas.
Cuando haces f"vector_{n}" el intérprete reemplaza {n}
por el valor de la variable n
en forma de cadena (str(n)
). Por lo que:
>>> n = 1
>>> f"vector_{n}"
'vector_1'
La diferencia es que son literales de cadena. Son considerablemente más eficientes que el uso de str.format
dado que se evita la generación de la cadena inicial primero y la llamada al método después, además de ser más legibles, por lo que deben usarse preferentemente. No obstante hay casos en los que la necesidad de dinamismo en tiempo de ejecución hace necesario usar str.format
, por lo qu no remplazan ni mucho menos a éste.
Literales de cadena unicode
Se denotan con una "u" de "unicode" delante de la cadena.
Su utilidad actual es escasa dado que es un remanente de Python 2. En Python 2 las cadenas (str
) son ASCII, por lo que se usaba u"" para generar literales de cadena Unicode. En Python 3 las cadenas usan todas "UTF-8" por defecto, por lo que el uso de u"" es redundante. De hecho, se eliminó de Python 3, pero posteriormente (a partir de Python 3.3) fue repuesto para hacer el código compatible con Python 2, por entonces mayoritario:
Su uso en Python 3 es incorrecto si no es por razones de retrocompatibilidad con el oficialmente extinto Python 2.
Python 2
>>> cad = "cigüeña"
>>> u_cad = u"cigüeña"
>>> cad == u_cad
__main__:1: UnicodeWarning: Unicode equal comparison failed to convert both arguments to Unicode - interpreting them as being unequal
False
>>> type(cad)
<type 'str'>
>>> type(u_cad)
<type 'unicode'>
Python 3
>>> cad = "cigüeña"
>>> u_cad = "cigüeña"
>>> cad == u_cad
True
>>> type(u_cad)
<class 'str'>
>>> type(cad)
<class 'str'>
Literales de cadena "crudos"
Se denotan con una "r" de "raw" delante del literal, r""
.
Básicamente lo que se encierra entre comillas, todo, es interpretado como un carácter literal. Es por tanto importante en el caso de \
, carácter que denota secuencias de escape,como \t
(tabulación), \n
nueva línea, \r
(retorno de carro), etc:
>>> print("Hola\n¿qué\ttal?")
Hola
¿qué tal?
>>> print(r"Hola\n¿qué\ttal?")
Hola\n¿qué\ttal?
Son útiles por tanto cuando necesitamos una cadena en la que todo sea interpretado como un carácter literal sin interpretar las secuencias de escape. Por ejemplo, a la hora de crear expresiones regulares.
En tu caso, cuando haces r"vector_{n}"
el atributo se crea con el nombre "vector_{n}"
literalmente, no con "vector_1"
:
>>> n = 1
>>> r"vector_{n}"
'vector_{n}'
Por eso luego te salta que el atributo vector_1
no existe, lo que se ha creado es una clave en el diccionario con valor 'vector_{n}', el cual por cierto es un nombre no válido para un atributo por los {}
.
Literales para cadenas de bytes
Por último, anteponiendo una "b" o "B" antes de un literal, b""
/B""
, creamos una instancia del tipo bytes
en lugar de str
. Solo puede contener caracteres ASCII y los bytes con valor numérico mayor a 127 tienen que representarse mediante secuencias de escape.
>>> b_cad = b"Eso vale 13\xe2\x82\xac"
>>> b_cad.decode("UTF-8")
'Eso vale 13€'
Son similares por tanto al antiguo str
de Python 2, de hecho en Python 2 son ignorados y son redundantes, igual que pasaba con u"" en Python 3.
Por lo tanto, cada prefijo crea cosas diferentes, no puedes cambiar f""
por r""
o b""
. En cambio, lo siguiente si es equivalente:
f"vector_{n}"
"vector_{}".format(n)
"vector_{numero}".format(numero=n)
"vector_{numero}".format_map({numero: n})
"vector_%d" % (n, )
"vector_" + str(n)
...