Skip to content

Instantly share code, notes, and snippets.

@juanescalona
Last active June 22, 2022 19:05
Show Gist options
  • Save juanescalona/63ee6e4bb415ba04cb191dd16c56cd2d to your computer and use it in GitHub Desktop.
Save juanescalona/63ee6e4bb415ba04cb191dd16c56cd2d to your computer and use it in GitHub Desktop.
Clase para validar, calcular dígito verificador y generar DNIs de Perú
from random import randint
class DniPeru:
def __init__(self):
self.numbers = (6, 7, 8, 9, 0, 1, 1, 2, 3, 4, 5)
self.letters = ('K', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J')
self.multiples = (3, 2, 7, 6, 5, 4, 3, 2)
def __index(self, dni):
""" Genera el índice de posición del dígito verificador """
dni = str(dni).replace('-', '').replace('.', '').strip().upper()
numdni = [*map(int, dni[:8])]
dsum = sum([x * y for x, y in [*zip(self.multiples, numdni)]])
key = 11 - (dsum % 11)
key = 0 if key == 11 else key
return key
def validate(self, dni):
""" Verifica que un DNI de Perú sea válido """
if len(dni) != 9:
raise ValueError('El DNI debe tener longitud 9.')
if dni[-1].isnumeric():
return self.numbers[self.__index(dni)] == int(dni[-1])
else:
return self.letters[self.__index(dni)] == dni[-1]
def dv(self, dni):
""" Calcula el dígito verificador para un DNI """
if len(dni) != 8:
raise ValueError('El DNI debe tener longitud 8.')
return {
'numeric': self.numbers[self.__index(dni)],
'letter': self.letters[self.__index(dni)]
}
def generate(self):
""" Genera un DNI válido para Perú al azar """
dni = str(randint(1000000, 99999999)).zfill(8)
dv = self.dv(dni)
return {
'numeric': dni + str(dv['numeric']),
'letter': dni + dv['letter']
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment