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.