associação pythonbrasil[11] django zope/plone planet Início Logado como (Entrar)

Revisão 1e 2003-11-16 18:23:39

Excluir mensagem

VerificadorDeCpf

Receita: Verificador de CPF

Esse módulo contém algumas funções e classes úteis para aplicações que envolvam cadastros e necessitem validar números de CPF antes de incluir no banco de dados. Além de útil, também é um bom exemplo de como otimizar código que lida com manipulação de números e strings, usando as funções reduce(), map() e list compreensions.

Código

   1 #/usr/bin/env python
   2 # -*- coding:UTF-8 -*-
   3 
   4 
   5 def _gen(cpf):
   6     """Gera o próximo dígito do número de CPF
   7 
   8     """
   9     res = []
  10     for i in range(len(cpf)):
  11         a = cpf[i]
  12         b = (len(cpf) + 1 - i)
  13         res.append(b * a)
  14 
  15     res = reduce(int.__add__, res) % 11
  16 
  17     if res > 1:
  18         return (11 - res)
  19     else:
  20         return 0
  21 
  22 
  23 def _translate(cpf):
  24     """Traduz o número como string na forma:
  25 
  26     123.456.789-10
  27 
  28     para a forma:
  29 
  30     12345678910
  31 
  32     """
  33     
  34     i = xrange(256)
  35     t = [' '] * 256
  36     e = ''.join([chr(x) for x in i if not chr(x).isdigit()])
  37     
  38     for x in i:
  39         if chr(x).isdigit():
  40             t[x] = chr(x)
  41             
  42     return cpf.translate(''.join(t), e)
  43 
  44 
  45 
  46 class CPF(object):
  47 
  48     _gen = staticmethod(_gen)
  49     _translate = staticmethod(_translate)
  50     
  51     def __init__(self, cpf):
  52         """O argumento cpf pode ser uma string nas formas:
  53 
  54         12345678910
  55         123.456.789-10
  56 
  57         ou uma lista ou tuple
  58         [1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 0]
  59         (1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 0)
  60 
  61         """
  62         
  63         if isinstance(cpf, basestring):
  64             if not cpf.isdigit():
  65                cpf = self._translate(cpf)
  66             
  67         self.cpf = [int(x) for x in cpf]
  68 
  69     def __getitem__(self, index):
  70         """Retorna o dígito em index como string
  71 
  72         """
  73         
  74         return self.cpf[index]
  75 
  76     def __repr__(self):
  77         """Retorna uma representação 'real', ou seja:
  78 
  79         eval(repr(cpf)) == cpf
  80         
  81         """
  82         
  83         return "CPF('%s')" % ''.join([str(x) for x in self.cpf])
  84 
  85     def __eq__(self, other):
  86         """Provê teste de igualdade para números de CPF
  87 
  88         """
  89 
  90         if isinstance(other, CPF):
  91             return self.cpf == other.cpf
  92         return False
  93     
  94     def __str__(self):
  95         """Retorna uma representação do CPF na forma:
  96 
  97         123.456.789-10
  98 
  99         """
 100 
 101         d = iter("..-")
 102         s = map(str, self.cpf)
 103         for i in xrange(3, 12, 4):
 104             s.insert(i, d.next())
 105         r = ''.join(s)
 106         return r
 107 
 108     def isValid(self):
 109         """Valida o número de cpf
 110 
 111         """
 112         
 113         s = self.cpf[:9]
 114         s.append(self._gen(s))
 115         s.append(self._gen(s))
 116         return s == self.cpf[:]

Exemplo de uso

   1 #/usr/bin/env python
   2 # -*- coding:UTF-8 -*-
   3 
   4 
   5 from cpf import CPF
   6 
   7 # Estes números foram gerados aleatoriamente :)
   8 
   9 VALIDO = "113.451.253-80"
  10 INVALIDO = "31354110274"
  11 
  12 # qualquer um dos dois formatos (com pontos ou não) pode ser usado
  13 
  14 valido = CPF(VALIDO)
  15 invalido = CPF(INVALIDO)
  16 
  17 assert valido.verificar()
  18 assert not invalido.verificar()

Volta para CookBook.


Pedro Werneck