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

Revisão 2e 2003-11-19 03:58:02

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


PedroWerneck