3. Fundamentos de Python

3.1. Script [bases_01]: operaciones elementales
El script [bases_01] presenta las primeras características de Python.
# ----------------------------------
def affiche(chaine):
# muestra cadena
print("chaine=%s" % chaine)
# ----------------------------------
def affiche_type(variable):
# muestra el tipo de variable
print("type[%s]=%s" % (variable, type(variable)))
# ----------------------------------
def f1(param):
# suma 10 a param
return param + 10
# ----------------------------------
def f2():
# devuelve una tupla de 3 valores
return "un", 0, 100
# -------------------------------- programa principal ------------------------------------
# esto es un comentario
# variable utilizada sin haber sido declarada
nom = "dupont"
# una salida a pantalla
print("nom=%s" % nom)
# una lista con elementos de tipo diferente
liste = ["un", "deux", 3, 4]
# su número de elementos
n = len(liste)
# un bucle
for i in range(n):
print("liste[%d]=%s" % (i, liste[i]))
# inicialización de 2 variables con una tupla
(chaine1, chaine2) = ("chaine1", "chaine2")
# concatenación de las 2 cadenas
chaine3 = chaine1 + chaine2
# visualización del resultado
print("[%s,%s,%s]" % (chaine1, chaine2, chaine3))
# uso de la función
affiche(chaine1)
# se puede conocer el tipo de una variable
affiche_type(n)
affiche_type(chaine1)
affiche_type(liste)
# el tipo de una variable puede cambiar durante la ejecución
n = "a changé"
affiche_type(n)
# una función puede devolver un resultado
res1 = f1(4)
print("res1=%s" % res1)
# una función puede devolver una lista de valores
(res1, res2, res3) = f2()
print("(res1,res2,res3)=[%s,%s,%s]" % (res1, res2, res3))
# se podrían haber almacenado estos valores en una variable
liste = f2()
for i in range(len(liste)):
print("liste[%s]=%s" % (i, liste[i]))
# pruebas
for i in range(len(liste)):
# solo muestra las cadenas
if type(liste[i]) == "str":
print("liste[%s]=%s" % (i, liste[i]))
# otras pruebas
for i in range(len(liste)):
# solo muestra los enteros >10
if type(liste[i]) == "int" and liste[i] > 10:
print("liste[%s]=%s" % (i, liste[i]))
# un bucle while
liste = (8, 5, 0, -2, 3, 4)
i = 0
somme = 0
while i < len(liste) and liste[i] > 0:
print("liste[%s]=%s" % (i, liste[i]))
somme += liste[i] # suma = suma + lista[i]
i += 1 # i = i + 1
print("somme=%s" % somme)
# fin del programa
Comentarios
- línea 2: la palabra clave def define una función;
- línea 2: la función recibe el parámetro [chaine]. No se indica el tipo del parámetro. Python utiliza exclusivamente el paso por valor. Este varía en función del dato:
- para un tipo simple (número, booleano…), este valor es el valor encapsulado por el dato (4, True…);
- para un tipo complejo (lista, clase…), este valor es la dirección del dato;
- líneas 3-4: el contenido de la función. Está sangrado a la derecha una tabulación. Es esta sangría, junto con el carácter : de la instrucción def, la que define el contenido de la función. Esto es válido para todas las instrucciones que tienen contenido: if, else, while, for, try, except;
- línea 4: la sintaxis utilizada aquí es [print('text1%F1text2%F2…' % data1, data2)]:
- los [%Fi] (aquí %s) son formatos de visualización:
- %s (string): para una cadena de caracteres;
- %d (decimal): para números enteros decimales con signo;
- %f (float): formato decimal para números reales;
- %e (exponencial): formato exponencial para un número real;
- …
- [data1, data2…] son las expresiones cuyo valor se desea mostrar:
- [data1] se mostrará con el formato F1;
- [data2] se mostrará con el formato F2;
- …
- línea 10: Python gestiona internamente el tipo de las variables. Se puede conocer el tipo de una variable con la función type(variable), que devuelve una variable de tipo «type». La expresión «%s» % (type(variable)) es una cadena de caracteres que representa el tipo de la variable;
- línea 25: el programa principal. Este suele aparecer (aunque no necesariamente) después de la definición de todas las funciones del script. Su contenido no está sangrado;
- línea 28: en Python no se declaran las variables. Python distingue entre mayúsculas y minúsculas. La variable Nom es diferente de la variable nom. Una cadena de caracteres puede ir entre comillas " o entre apóstrofos '. Por lo tanto, se puede escribir 'dupont' o "dupont";
- línea 34: hay una diferencia entre una tupla (1,2,3) (fíjate en los paréntesis) y una lista [1,2,3] (fíjate en los corchetes). La tupla no es modificable, mientras que la lista sí lo es. En ambos casos, el elemento n.º i se escribe [i];
- línea 40: range(n) es la tupla (0,1,2,…,n-1);
- línea 41: el formato %d se utiliza para los números enteros con signo;
- línea 74: len(var) es el número de elementos de la colección var (tupla, lista, diccionario…);
- línea 84: la estructura [for in …] permite iterar sobre una estructura iterable. Las listas y las tuplas son elementos iterables;
- línea 86: los demás operadores booleanos son or y not;
- línea 93: suma los números >0 de la lista;
Los resultados en pantalla son los siguientes:
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/bases/bases_01.py
nom=dupont
liste[0]=un
liste[1]=deux
liste[2]=3
liste[3]=4
[chaine1,chaine2,chaine1chaine2]
chaine=chaine1
type[4]=<class 'int'>
type[chaine1]=<class 'str'>
type[['un', 'deux', 3, 4]]=<class 'list'>
type[a changé]=<class 'str'>
res1=14
(res1,res2,res3)=[un,0,100]
liste[0]=un
liste[1]=0
liste[2]=100
liste[0]=8
liste[1]=5
somme=13
Process finished with exit code 0
3.2. Script [bases_02]: cadenas de formato
Python 3 ha introducido una nueva forma de formatear cadenas de caracteres:
# cadenas de formato
# los formatos son los del lenguaje C
# entero
int1 = 10
print(f"[int1={int1}]")
print(f"[int1={int1:4d}]")
print(f"[int1={int1:04d}]")
# flotante
float1=8.2
print(f"[float1={float1}]")
print(f"[float1={float1:8.2f}]")
print(f"[float1={float1:.3e}]")
# string
str1="abcd"
print(f"[str1={str1}]")
print(f"[str1={str1:8s}]")
str2="jean de florette"
print(f"[{str2:20.10s}]")
# las cadenas formateadas se pueden asignar a variables
str3=f"[{str2:20.10s}]"
print(str3)
La sintaxis de la cadena formateada es la siguiente:
con:
- [expri]: una expresión;
- [formati]: el formato de la expresión [expri]. Estos formatos son los del lenguaje C:
- %d: para números enteros;
- %f: notación decimal para los números reales;
- %e: notación exponencial para los números reales;
- %s: para cadenas de caracteres. Es el formato utilizado cuando no se utiliza ningún formato para [expri];
- %nd, %nf, %ns: muestra [expri] en n caracteres: la cadena se trunca o se completa con espacios;
- línea 7: [04d], entero de 4 caracteres completado a la izquierda con ceros;
- línea 11: [8.2f], número real decimal de 8 caracteres, 2 de ellos después de la coma;
- línea 12: [.3e], número real en forma exponencial con 3 decimales para la mantisa;
- línea 18: [20.10s], los 10 primeros caracteres de una cadena completada con espacios hasta alcanzar los 20 caracteres;
Los resultados de la ejecución son los siguientes:
3.3. Script [bases_03]: cambios de tipo
Aquí nos centramos en los cambios de tipo con datos de tipo str (cadena de caracteres), int (entero), float (real) y bool (booleano).
# cambios de tipo
# int --> str, float, bool
x = 4
print(x, type(x))
x = str(4)
print(x, type(x))
x = float(4)
print(x, type(x))
x = bool(4)
print(x, type(x))
# bool --> int, float, str
x = True
print(x, type(x))
x = int(True)
print(x, type(x))
x = float(True)
print(x, type(x))
x = str(True)
print(x, type(x))
# str --> int, float, bool
x = "4"
print(x, type(x))
x = int("4")
print(x, type(x))
x = float("4")
print(x, type(x))
x = bool("4")
print(x, type(x))
# float --> str, int, bool
x = 4.32
print(x, type(x))
x = str(4.32)
print(x, type(x))
x = int(4.32)
print(x, type(x))
x = bool(4.32)
print(x, type(x))
# gestión de errores de cambio de tipo
try:
x = int("abc")
print(x, type(x))
except ValueError as erreur:
print(erreur)
# casos diversos
x = bool("abc")
print(x, type(x))
x = bool("")
print(x, type(x))
x = bool(0)
print(x, type(x))
x = None
print(x, type(x))
x = bool(None)
print(x, type(x))
x = bool(0.0)
print(x, type(x))
# todos los datos son instancias de clase y, como tales, tienen métodos
# cadena de caracteres
str1 = "abc"
print(str1.capitalize())
# entero
int1 = 4
print(int1.bit_length())
# booleano
bool1=True
print(bool1.conjugate())
# número real
float1=8.2
print (float1.is_integer())
Son posibles numerosos cambios de tipo. Algunos pueden fallar, como el de las líneas 46-47, que intentan transformar la cadena «abc» en un entero. Hemos gestionado el error con una estructura try / except. Una forma general de esta estructura
es la siguiente:
try:
actions
except Exception as ex:
actions
finally:
actions
Si alguna de las acciones del try lanza una excepción (señala un error), se produce una ramificación inmediata a la cláusula except. Si las acciones del try no lanzan ninguna excepción, la cláusula except se ignora. Los atributos Exception y ex de la instrucción except son opcionales. Cuando están presentes, Exception especifica el tipo de excepción interceptada por la instrucción except y ex contiene la excepción que se ha producido. Puede haber varias instrucciones except, si se desea gestionar diferentes tipos de excepciones en el mismo try.
La instrucción finally es opcional. Si está presente, las acciones de finally se ejecutan siempre, haya habido o no una excepción.
Volveremos sobre las excepciones más adelante.
Las líneas 49-61 muestran diversos intentos de transformar datos de tipo str, int, float, NoneType en booleanos. Esto siempre es posible. Las reglas son las siguientes:
- bool(int i) es igual a False si i es igual a 0, y a True en todos los demás casos;
- bool(float f) es igual a False si f es igual a 0.0, True en todos los demás casos;
- bool(str cadena) es igual a False si cadena tiene 0 caracteres, True en todos los demás casos;
- bool(None) es False. None es un valor especial que significa que la variable existe pero no tiene valor.
Los resultados en pantalla son los siguientes:
Cabe señalar que todos los datos son objetos, es decir, instancias de clase. Esto significa que pueden tener métodos. Así lo muestran las líneas 63-75 del código. No pretendemos aquí explicar qué hacen los métodos utilizados, sino simplemente mostrar que existen.
3.4. Script [bases_04]: ámbito de las variables
El script [bases_04] muestra que Python no tiene el concepto de variable de ámbito de bloque:
# ámbito de las variables
i = 4
if True:
i += 1
j = 7
print(f"i={i}, j={j}")
Resultados
Comentarios
Los resultados muestran dos cosas:
- línea 4: la variable [i] del bloque [if] es la misma que la variable i utilizada en la línea 2;
- línea 6: la variable [j] es la que se inicializa en el bloque [if];
En algunos lenguajes, en los que se declaran las variables, una variable definida en un bloque (como el de las líneas 3-5) no es conocida fuera de este. En Python, no ocurre tal cosa.
3.5. Script [bases_05]: listas - 1
El script [bases_05] es el siguiente:
# listas unidimensionales
# inicialización
list1 = [0, 1, 2, 3, 4, 5]
# recorrido - 1
print(f"list1 a {len(list1)} éléments")
for i in range(len(list1)):
print(f"list1[{i}]={list1[i]}")
list1[1] = 10
# recorrido - 2
print(f"list1 a {len(list1)} éléments")
for element in list1:
print(element)
# adición de dos elementos
list1[len(list1):] = [10, 11]
# el formato %s permite mostrar la lista en una sola línea
print("%s" % list1)
# eliminación de los dos últimos elementos
list1[len(list1) - 2:] = []
# el formato predeterminado permite mostrar la lista en una sola línea
print(f"{list1}")
# Añadido de una lista al principio de la lista
list1[:0] = [-10, -11, -12]
print(f"{list1}")
# Inserción de dos elementos en el centro de la lista
list1[3:3] = [100, 101]
print(f"{list1}")
# eliminación de dos elementos en el centro de la lista
list1[3:4] = []
print(f"{list1}")
Notas:
- la notación tabla[i:j] designa los elementos i a j-1 de la tabla;
- la notación [i:] designa los elementos i y siguientes de la matriz;
- la notación [:i] designa los elementos del 0 al i-1 de la matriz;
- línea 19: print (%s) % (list1) muestra la cadena de caracteres: «[ list1[0], list1[2]…, list1[n-1]]»;
- línea 24: la notación print ('f{list1}') hace lo mismo;
Resultados
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/bases/bases_05.py
list1 a 6 éléments
list1[0]=0
list1[1]=1
list1[2]=2
list1[3]=3
list1[4]=4
list1[5]=5
list1 a 6 éléments
0
10
2
3
4
5
[0, 10, 2, 3, 4, 5, 10, 11]
[0, 10, 2, 3, 4, 5]
[-10, -11, -12, 0, 10, 2, 3, 4, 5]
[-10, -11, -12, 100, 101, 0, 10, 2, 3, 4, 5]
[-10, -11, -12, 101, 0, 10, 2, 3, 4, 5]
Process finished with exit code 0
3.6. Script [bases_06]: listas - 2
El código anterior se puede escribir de otra forma (bases_06) utilizando ciertos métodos de las listas:
# listas unidimensionales
# inicialización
list1 = [0, 1, 2, 3, 4, 5]
# recorrido - 1
print(f"list1 a {len(list1)} éléments")
for i in range(len(list1)):
print(f"list1[{i}]={list1[i]}")
# modificación de un elemento
list1[1] = 10
# recorrido - 2
print(f"list1 a {len(list1)} éléments")
for element in list1:
print(element)
# adición de dos elementos
list1.extend([10, 11])
print(f"{list1}")
# eliminación de los dos últimos elementos
del list1[len(list1) - 2:]
print(f"{list1}")
# Añadir una tupla al principio de la lista
for i in (-12, -11, -10):
list1.insert(0, i)
print(f"{list1}")
# inserción en el centro de la lista
for i in (101, 100):
list1.insert(3, i)
print(f"{list1}")
# eliminación en el centro de la lista
del list1[3:4]
print(f"{list1}")
Los resultados obtenidos son los mismos que con el version anterior.
3.7. script [bases_07]: el diccionario
El script [bases_07] muestra cómo definir y utilizar un diccionario, a veces denominado tabla asociativa.
# una función que comprueba si la clave «marido» existe en el diccionario «cónyuges»
def existe(conjoints, mari):
if mari in conjoints:
print(f"La clé [{mari}] existe associée à la valeur [{conjoints[mari]}]")
else:
print(f"La clé [{mari}] n'existe pas")
# ----------------------------- Main
# un diccionario
conjoints = {"Pierre": "Gisèle", "Paul": "Virginie", "Jacques": "Lucette", "Jean": ""}
# recorrido - 1
print(f"Nombre d'éléments du dictionnaire : {len(conjoints)}")
for (clé, valeur) in conjoints.items():
print(f"conjoints[{clé}]={valeur}")
# lista de claves del diccionario
print("liste des clés-------------")
clés = conjoints.keys()
print(f"{clés}")
# lista de valores del diccionario
print("liste des valeurs------------")
valeurs = conjoints.values()
print(f"{valeurs}")
# búsqueda de una clave
existe(conjoints, "Jacques")
existe(conjoints, "Lucette")
existe(conjoints, "Jean")
# eliminación de una clave-valor
del (conjoints["Jean"])
print(f"Nombre d'éléments du dictionnaire : {len(conjoints)}")
print(f"{conjoints}")
# las claves y los valores de un diccionario no son listas
print(f"type des clés : {type(clés)}")
print(f"type des valeurs : {type(valeurs)}")
# se pueden convertir en listas
lclés = list(clés)
print(f"clés : {type(lclés)}, {lclés}")
lvaleurs = list(valeurs)
print(f"valeurs : {type(lvaleurs)}, {lvaleurs}")
Notas:
- línea 11: la definición fija de un diccionario;
- línea 15: conjoints.items() devuelve la lista de pares (clave, valor) del diccionario;
- línea 20: conjoints.keys() devuelve las claves del diccionario;
- línea 25: conjoints.values() devuelve los valores del diccionario conjoints;
- línea 3: mari in conjoints devuelve True si la clave mari existe en el diccionario conjoints; de lo contrario, devuelve False;
- línea 36: un diccionario se puede mostrar en una sola línea.
Resultados
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/bases/bases_07.py
Nombre d'éléments du dictionnaire : 4
conjoints[Pierre]=Gisèle
conjoints[Paul]=Virginie
conjoints[Jacques]=Lucette
conjoints[Jean]=
liste des clés-------------
dict_keys(['Pierre', 'Paul', 'Jacques', 'Jean'])
liste des valeurs------------
dict_values(['Gisèle', 'Virginie', 'Lucette', ''])
La clé [Jacques] existe associée à la valeur [Lucette]
La clé [Lucette] n'existe pas
La clé [Jean] existe associée à la valeur []
Nombre d'éléments du dictionnaire : 3
{'Pierre': 'Gisèle', 'Paul': 'Virginie', 'Jacques': 'Lucette'}
type des clés : <class 'dict_keys'>
type des valeurs : <class 'dict_values'>
clés : <class 'list'>, ['Pierre', 'Paul', 'Jacques']
valeurs : <class 'list'>, ['Gisèle', 'Virginie', 'Lucette']
Process finished with exit code 0
Notas:
- Cabe señalar, en las líneas 16 y 17 de los resultados, que las claves y los valores de un diccionario no forman una lista, sino un tipo «dict_keys»;
- líneas 18-19: un simple cambio de tipo permite convertirlos en un tipo [list];
3.8. script [bases_08]: las tuplas
La tupla tiene similitudes con la lista, pero no es modificable:
# tuplas
# inicialización
tuple1 = (0, 1, 2, 3, 4, 5)
# recorrido - 1
print(f"tuple1 a {len(tuple1)} elements")
for i in range(len(tuple1)):
print(f"tuple1[{i}]={tuple1[i]}")
# recorrido - 2
print(f"tuple1 a {len(tuple1)} elements")
for element in tuple1:
print(element)
# un tupla se puede mostrar en una línea
print(f"tuple1={tuple1}")
# una tupla no se puede modificar
tuple1[0] = 10
Resultados
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/bases/bases_08.py
tuple1 a 6 elements
tuple1[0]=0
tuple1[1]=1
tuple1[2]=2
tuple1[3]=3
tuple1[4]=4
tuple1[5]=5
tuple1 a 6 elements
0
1
2
3
4
5
tuple1=(0, 1, 2, 3, 4, 5)
Traceback (most recent call last):
File "C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/bases/bases_08.py", line 19, in <module>
tuple1[0] = 10
TypeError: 'tuple' object does not support item assignment
Process finished with exit code 1
Notas:
- líneas 17-20 de los resultados: muestran que una tupla no se puede modificar.
3.9. Script [bases_09]: listas y diccionarios multidimensionales
El script [bases_09] muestra cómo definir y utilizar una lista o un diccionario multidimensional:
# listas multidimensionales
# inicialización
multi = [[0, 1, 2], [10, 11, 12, 13], [20, 21, 22, 23, 24]]
# recorrido
for i1 in range(len(multi)):
for i2 in range(len(multi[i1])):
print(f"multi[{i1}][{i2}]={multi[i1][i2]}")
# visualización en una línea
print(f"multi={multi}")
# diccionarios multidimensionales
# inicialización
multi = {"zéro": [0, 1], "un": [10, 11, 12, 13], "deux": [20, 21, 22, 23, 24]}
# recorrido
for (clé, valeur) in multi.items():
for i2 in range(len(valeur)):
print(f"multi[{clé}][{i2}]={multi[clé][i2]}")
# visualización en una línea
print(f"multi={multi}")
Comentarios
- línea 7: multi[i1] es una lista;
- línea 18: «valor» es una lista;
Resultados
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/bases/bases_09.py
multi[0][0]=0
multi[0][1]=1
multi[0][2]=2
multi[1][0]=10
multi[1][1]=11
multi[1][2]=12
multi[1][3]=13
multi[2][0]=20
multi[2][1]=21
multi[2][2]=22
multi[2][3]=23
multi[2][4]=24
multi=[[0, 1, 2], [10, 11, 12, 13], [20, 21, 22, 23, 24]]
multi[zéro][0]=0
multi[zéro][1]=1
multi[un][0]=10
multi[un][1]=11
multi[un][2]=12
multi[un][3]=13
multi[deux][0]=20
multi[deux][1]=21
multi[deux][2]=22
multi[deux][3]=23
multi[deux][4]=24
multi={'zéro': [0, 1], 'un': [10, 11, 12, 13], 'deux': [20, 21, 22, 23, 24]}
Process finished with exit code 0
3.10. Script [bases_10]: enlaces entre cadenas y listas
El script [bases_10] muestra cómo recuperar en una lista los elementos de una cadena separados por un mismo separador.
# cadena a lista
chaine = '1:2:3:4'
liste = chaine.split(':')
print(type(liste))
# visualización de lista
print(f"liste a {len(liste)} éléments")
print(f"liste={liste}")
# de lista a cadena
chaine2 = ":".join(liste)
print(f"chaine2={chaine2}")
# añadamos un campo vacío
chaine += ":"
print(f"chaine={chaine}")
liste = chaine.split(":")
# visualización de lista
print(f"liste a {len(liste)} éléments")
print(f"liste={liste}")
# añadamos de nuevo un campo vacío
chaine += ":"
print(f"chaine={chaine}")
liste = chaine.split(":")
# visualización de lista
print(f"liste a {len(liste)} éléments")
print(f"liste={liste}")
Notas:
- línea 3: el método chaine.split(separador) divide la cadena de caracteres chaine en elementos separados por séparateur y los devuelve en forma de lista. Así, la expresión '1:2:3:4'.split(":") tiene como valor la lista ('1','2','3','4');
- línea 11: 'separador'.join(lista) tiene como valor la cadena de caracteres 'lista[0]+separador+lista[1]+separador+…'.
Resultados
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/bases/bases_10.py
<class 'list'>
liste a 4 éléments
liste=['1', '2', '3', '4']
chaine2=1:2:3:4
chaine=1:2:3:4:
liste a 5 éléments
liste=['1', '2', '3', '4', '']
chaine=1:2:3:4::
liste a 6 éléments
liste=['1', '2', '3', '4', '', '']
Process finished with exit code 0
3.11. Script [bases_11]: expresiones regulares
El script [bases_11] muestra cómo utilizar expresiones regulares:
# se importa el módulo de expresiones regulares
import re
# --------------------------------------------------------------------------
def compare(modèle, chaine):
# compara la cadena [chaîne] con el patrón [modèle]
# muestra los resultados
print(f"\nRésultats({chaine},{modèle})")
match = re.match(modèle, chaine)
if match:
print(match.groups())
else:
print(f"La chaîne [{chaine}] ne correspond pas au modèle [{modèle}]")
# expresiones regulares en Python
# recuperar los diferentes campos de una cadena
# el patrón: una secuencia de dígitos rodeada de caracteres cualquiera
# solo queremos recuperar la secuencia de números
modèle = r"^.*?(\d+).*?$"
# comparamos la cadena con el patrón
compare(modèle, "xyz1234abcd")
compare(modèle, "12 34")
compare(modèle, "abcd")
# el patrón: una secuencia de dígitos rodeada de caracteres arbitrarios
# queremos la secuencia de números, así como los campos que la preceden y la siguen
modèle = r"^(.*?)(\d+)(.*?)$"
# comparamos la cadena con el patrón
compare(modèle, "xyz1234abcd")
compare(modèle, "12 34")
compare(modèle, "abcd")
# el patrón: una fecha en formato dd/mm/aa
modèle = r"^\s*(\d\d)\/(\d\d)\/(\d\d)\s*$"
compare(modèle, "10/05/97")
compare(modèle, " 04/04/01 ")
compare(modèle, "5/1/01")
# el patrón: un número decimal
modèle = r"^\s*([+-]?)\s*(\d+\.\d*|\.\d+|\d+)\s*$"
compare(modèle, "187.8")
compare(modèle, "-0.6")
compare(modèle, "4")
compare(modèle, ".6")
compare(modèle, "4.")
compare(modèle, " + 4")
# fin
Notas:
- fíjese en el módulo [re] importado en la línea 2. Es este el que contiene las funciones de gestión de expresiones regulares;
- línea 10: la comparación de una cadena con una expresión regular (patrón) devuelve el valor booleano True si la cadena coincide con el patrón, y False en caso contrario;
- línea 12: match.groups() es una tupla cuyos elementos son las partes de la cadena que se corresponden con los elementos de la expresión regular entre paréntesis. En el patrón:
- ^.*?(\d+).*?, match.groups() será una tupla de un elemento porque hay un paréntesis;
- ^(.*?)(\d+)(.*?)$, match.groups() será una tupla de 3 elementos porque hay tres paréntesis;
- línea 21: una expresión regular literal se escribe r"xxx". Es el símbolo r el que convierte la cadena en una expresión regular;
Las expresiones regulares nos permiten comprobar el formato de una cadena de caracteres. Así, podemos verificar que una cadena que representa una fecha tiene el formato dd/mm/aa. Para ello, se utiliza un patrón y se compara la cadena con dicho patrón. Así, en este ejemplo, d, m y a deben ser números. El patrón de un formato de fecha válido es entonces «\d\d/\d\d/\d\d», donde el símbolo \d designa un dígito. Los símbolos que se pueden utilizar en un patrón son los siguientes:
Carácter | Descripción |
\ | Marca el carácter siguiente como carácter especial o literal. Por ejemplo, «n» corresponde al carácter «n», mientras que «\n» corresponde a un carácter de nueva línea. La secuencia «\\» corresponde a «\», mientras que «\»( corresponde a «(». |
^ | Corresponde al inicio de la cadena. |
$ | Corresponde al final de la cadena. |
* | Corresponde al carácter anterior, cero o más veces. Así, «zo*» corresponde a «z» o a «zoo». |
+ | Corresponde al carácter anterior, una o varias veces. Así, «zo+» corresponde a «zoo», pero no a «z». |
? | Corresponde al carácter anterior, cero o una vez. Por ejemplo, «a?ve?» corresponde a «ve» en «lever». |
. | Corresponde a cualquier carácter único, excepto al carácter de nueva línea. |
(plantilla) | Busca modèle y memoriza la coincidencia. La subcadena coincidente se puede extraer de la colección match.groups(). Para encontrar coincidencias con caracteres entre paréntesis ( ), utiliza «\(» o «\)». |
x|y | Coincide con x o con y. Por ejemplo, «z|foot» coincide con «z» o con «foot». «(z|f)oo» coincide con «zoo» o con «foo». |
{n} | n es un número entero no negativo. Corresponde exactamente a n multiplicado por el carácter. Por ejemplo, «o{2}» no corresponde a «o» en «Bob», sino a las dos primeras «o» en «fooooot». |
{n,} | n es un número entero no negativo. Corresponde al menos a n veces el carácter. Por ejemplo, «o{2,}» no coincide con la «o» de «Bob», sino con todas las «o» de «fooooot». «o{1,}» equivale a «o+» y «o{0,}» equivale a «o*». |
{n,m} | m y n son números enteros no negativos. Corresponde al menos a n y como máximo a m veces el carácter. Por ejemplo, «o{1,3}» corresponde a las tres primeras «o» de «foooooot» y «o{0,1}» equivale a «o?». |
[xyz] | Conjunto de caracteres. Coincide con uno de los caracteres indicados. Por ejemplo, «[abc]» coincide con «a» en «plat». |
[^xyz] | Conjunto de caracteres negativo. Corresponde a cualquier carácter no indicado. Por ejemplo, «[^abc]» corresponde a «p» en «plat». |
[a-z] | Rango de caracteres. Corresponde a cualquier carácter de la serie especificada. Por ejemplo, «[a-z]» corresponde a cualquier carácter alfabético minúsculo comprendido entre «a» y «z». |
[^m-z] | Rango de caracteres negativo. Corresponde a cualquier carácter que no se encuentre en la serie especificada. Por ejemplo, «[^m-z]» corresponde a cualquier carácter que no se encuentre entre «m» y «z». |
\b | Corresponde a un límite que representa una palabra, es decir, a la posición entre una palabra y un espacio. Por ejemplo, «er\b» corresponde a «er» en «lever», pero no a «er» en «verbe». |
\B | Corresponde a un límite que no representa una palabra. «en*t\B» corresponde a «ent» en «bien entendu». |
\d | Corresponde a un carácter que representa un dígito. Equivale a [0-9]. |
\D | Corresponde a un carácter que no representa un dígito. Equivale a [^0-9]. |
\f | Corresponde a un carácter de salto de página. |
\n | Corresponde a un carácter de nueva línea. |
\r | Corresponde a un carácter de retorno de carro. |
\s | Corresponde a cualquier espacio en blanco, incluyendo el espacio, la tabulación, el salto de página, etc. Equivale a «[ \f\n\r\t\v]». |
\S | Corresponde a cualquier carácter de espacio no en blanco. Equivale a «[^ \f\n\r\t\v]». |
\t | Corresponde a un carácter de tabulación. |
\v | Corresponde a un carácter de tabulación vertical. |
\w | Corresponde a cualquier carácter que represente una palabra e incluya un guión bajo. Equivale a «[A-Za-z0-9_]». |
\W | Coincide con cualquier carácter que no represente una palabra. Equivale a «[^A-Za-z0-9_]». |
\num | Corresponde a num, donde num es un número entero positivo. Hace referencia a las coincidencias almacenadas. Por ejemplo, «(.)\1» corresponde a dos caracteres idénticos consecutivos. |
\n | Corresponde a n, donde n es un valor de escape octal. Los valores de escape octales deben tener 1, 2 o 3 dígitos. Por ejemplo, «\11» y «\011» corresponden ambos a un carácter de tabulación. «\0011» equivale a «\001» y «1». Los valores de escape octales no deben superar 256. Si fuera así, solo se tendrían en cuenta los dos primeros dígitos en la expresión. Permite utilizar los códigos ASCII en expresiones regulares. |
\xn | Corresponde a n, donde n es un valor de escape hexadecimal. Los valores de escape hexadecimales deben constar obligatoriamente de dos dígitos. Por ejemplo, «\x41» corresponde a «A». «\x041» equivale a «\x04» y «1». Permite utilizar los códigos ASCII en expresiones regulares. |
Un elemento de una plantilla puede aparecer una o varias veces. Veamos algunos ejemplos relacionados con el símbolo \d, que representa un dígito:
plantilla | significado |
\d | un dígito |
\d? | 0 o 1 dígito |
\d* | 0 o más dígitos |
\d+ | 1 o más dígitos |
\d{2} | 2 dígitos |
\d{3,} | al menos 3 dígitos |
\d{5,7} | entre 5 y 7 dígitos |
Imaginemos ahora el modelo capaz de describir el formato esperado para una cadena de caracteres:
cadena buscada | modelo |
una fecha en formato dd/mm/aa | \d{2}/\d{2}/\d{2} |
una hora en formato hh:mm:ss | \d{2}:\d{2}:\d{2} |
un número entero sin signo | \d+ |
una secuencia de espacios, que puede estar vacía | \s* |
un número entero sin signo que puede ir precedido o seguido de espacios | \s*\d+\s* |
un número entero que puede ser con signo y estar precedido o seguido de espacios | \s*[+|-]?\s*\d+\s* |
un número real sin signo que puede ir precedido o seguido de espacios | \s*\d+(.\d*)?\s* |
un número real que puede ser con signo y estar precedido o seguido de espacios | \s*[+-]?\s*\d+(.\d*)?\s* |
una cadena que contenga la palabra «justo» | \bjusto\b |
Se puede especificar dónde se busca el patrón en la cadena:
patrón | significado |
^patrón | el patrón comienza la cadena |
patrón$ | el patrón termina la cadena |
^patrón$ | el patrón comienza y termina la cadena |
patrón | el patrón se busca en toda la cadena, empezando por el principio de la misma. |
cadena buscada | patrón |
una cadena que termina con un signo de exclamación | !$ |
una cadena que termina en un punto | \.$ |
una cadena que comienza con la secuencia // | ^// |
una cadena que contiene solo una palabra, seguida o precedida opcionalmente de espacios | ^\s*\w+\s*$ |
una cadena que contenga dos palabras, opcionalmente precedidas o seguidas de espacios | ^\s*\w+\s*\w+\s*$ |
una cadena que contenga la palabra «secret» | \bsecret\b |
Los subconjuntos de un patrón pueden «extraerse». De este modo, no solo se puede comprobar si una cadena se ajusta a un patrón concreto, sino que también se pueden extraer de dicha cadena los elementos que corresponden a los subconjuntos del patrón que se han encerrado entre paréntesis. Así, si analizamos una cadena que contiene una fecha dd/mm/aa y queremos además recuperar los elementos dd, mm, aa de esa fecha, utilizaremos el patrón (\d\d)/(\d\d)/(\d\d).
Resultados del script
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/bases/bases_11.py
Résultats(xyz1234abcd,^.*?(\d+).*?$)
('1234',)
Résultats(12 34,^.*?(\d+).*?$)
('12',)
Résultats(abcd,^.*?(\d+).*?$)
La chaîne [abcd] ne correspond pas au modèle [^.*?(\d+).*?$]
Résultats(xyz1234abcd,^(.*?)(\d+)(.*?)$)
('xyz', '1234', 'abcd')
Résultats(12 34,^(.*?)(\d+)(.*?)$)
('', '12', ' 34')
Résultats(abcd,^(.*?)(\d+)(.*?)$)
La chaîne [abcd] ne correspond pas au modèle [^(.*?)(\d+)(.*?)$]
Résultats(10/05/97,^\s*(\d\d)\/(\d\d)\/(\d\d)\s*$)
('10', '05', '97')
Résultats( 04/04/01 ,^\s*(\d\d)\/(\d\d)\/(\d\d)\s*$)
('04', '04', '01')
Résultats(5/1/01,^\s*(\d\d)\/(\d\d)\/(\d\d)\s*$)
La chaîne [5/1/01] ne correspond pas au modèle [^\s*(\d\d)\/(\d\d)\/(\d\d)\s*$]
Résultats(187.8,^\s*([+-]?)\s*(\d+\.\d*|\.\d+|\d+)\s*$)
('', '187.8')
Résultats(-0.6,^\s*([+-]?)\s*(\d+\.\d*|\.\d+|\d+)\s*$)
('-', '0.6')
Résultats(4,^\s*([+-]?)\s*(\d+\.\d*|\.\d+|\d+)\s*$)
('', '4')
Résultats(.6,^\s*([+-]?)\s*(\d+\.\d*|\.\d+|\d+)\s*$)
('', '.6')
Résultats(4.,^\s*([+-]?)\s*(\d+\.\d*|\.\d+|\d+)\s*$)
('', '4.')
Résultats( + 4,^\s*([+-]?)\s*(\d+\.\d*|\.\d+|\d+)\s*$)
('+', '4')
Process finished with exit code 0