En este post vamos a ver como validar una cadena de texto y verificar que es un DNI o NIF válido en python.
Algoritmo para validar una cadena de texto como un DNI o NIF:
-
El string o cadena de texto debe tener una longitud de 9 caracteres
-
Los caracteres del 1 al 8 deben ser números
-
El último dígito (dígito de control) se calcula dividiendo el número del DNI entre 23. El resto de la división (operación normalmente conocida como módulo) indicará la letra que debe ocupar la posición 9 del string según la tabla siguiente:
Resto
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Letra
T
R
W
A
G
M
Y
F
P
D
X
B
N
J
Z
S
Q
V
H
L
C
K
E
-
Como punto extra, la administración indica que los siguientes DNI no son válidos independientemente que cumplan la validación explicada en los puntos anteriores: 00000000T, 00000001R y 99999999R.
Como validar un DNI en python
Para validar en python un DNI según el algoritmo explicado en el apartado anterior, simplemente deberíamos tener el siguiente código:
import re
class Validaciones:
REGEXP = "[0-9]{8}[A-Z]"
DIGITO_CONTROL = "TRWAGMYFPDXBNJZSQVHLCKE"
INVALIDOS = {"00000000T", "00000001R", "99999999R"}
def __init__(self):
pass
def validar_dni(self, dni: str) -> bool:
return dni not in self.INVALIDOS \ # <1>
and re.match(self.REGEXP, dni) is not None \ # <2>
and dni[8] == self.DIGITO_CONTROL[int(dni[0:8]) % 23] # <3>
-
Lo primero que hacemos es asegurarnos de que el string no es ninguno de los DNI no válidos que fija el Ministerio de Interior.
-
Después, mediante una expresión regular, validamos que el string tenga 8 números y una letra al final (en este punto, solo estamos validando que la cadena de texto esté bien formada).
-
Para terminar, no basta con que el último dígito sea una letra, tiene que cumplir que el último carácter se corresponda con el dígito de control de la tabla después de aplicar la operación módulo 23.
Para ver que realmente es correcto el algoritmo anterior, podríamos definir un main para ver la salida de los resultados:
import re
class Validaciones:
...
if __name__ == '__main__':
# DNI que no son válidos por el Ministerio de interior
print(Validaciones().validar_dni("00000000T"))
print(Validaciones().validar_dni("00000001R"))
print(Validaciones().validar_dni("99999999R"))
# Strings que no cumplen la expresion regular
print(Validaciones().validar_dni("0123"))
print(Validaciones().validar_dni("01234A67Z"))
print(Validaciones().validar_dni("012345678-"))
print(Validaciones().validar_dni("0123456789"))
# DNI que si cumplen todas las validaciones
print(Validaciones().validar_dni("12345678Z"))
print(Validaciones().validar_dni("45673254S"))
print(Validaciones().validar_dni("72849506L"))
Como has podido comprobar al leer este post, validar un DNI en python es muy sencillo.