转自:http://my.oschina.net/moooofly/blog/147958
原来的天朝良民证是15位,构成如下:
1~6位:地址码。采用的是行政区划代码,可以去 统计局的网站 查。
7~12位:生日期码。构成为yymmdd。
13~15位:顺序码。每个地区出生人口按顺序递增,最后一位奇数分给男的,偶数分给女的。
18位则有2点改动:
1.生日期码变为8位,构成为yyyymmdd。
2.增加校验码,即第18位。按照ISO 7064:1983.MOD 11-2校验码计算。
计算方法很无聊:
- 将身份证号码的前17位数分别乘以不同的系数。从第一位到第十七位的系数分别为:7 9 10 5 8 4 2 1 6 3 7 9 10 5 8 4 2
- 将这17位数字和系数相乘的结果相加。
- 用加出来和除以11,得到余数。
- 余数的结果只可能为0 1 2 3 4 5 6 7 8 9 10这11种,分别对应的最后一位身份证的号码为1 0 X 9 8 7 6 5 4 3 2。
弄懂这个后,很快就能写出Python的计算程序了:
1 | s = "34052419800101001" |
4 | sum = int (s[ 0 ]) * 7 + int (s[ 1 ]) * 9 + int (s[ 2 ]) * 10 + int (s[ 3 ]) * 5 + int (s[ 4 ]) * 8 + int (s[ 5 ]) * 4 + int (s[ 6 ]) * 2 + int (s[ 7 ]) * 1 + int (s[ 8 ]) * 6 + int (s[ 9 ]) * 3 + int (s[ 10 ]) * 7 + int (s[ 11 ]) * 9 + int (s[ 12 ]) * 10 + int (s[ 13 ]) * 5 + int (s[ 14 ]) * 8 + int (s[ 15 ]) * 4 + int (s[ 16 ]) * 2 |
7 | print '10X98765432' [ sum % 11 ] |
有没有觉得计算总和非常无语,下面来简化代码:
01 | s = "34052419800101001" |
04 | temp = zip (s[ 0 : 17 ], [ 7 , 9 , 10 , 5 , 8 , 4 , 2 , 1 , 6 , 3 , 7 , 9 , 10 , 5 , 8 , 4 , 2 ]) |
08 | temp2 = map ( lambda x: int (x[ 0 ]) * x[ 1 ], temp) |
18 | print '10X98765432' [temp3 % 11 ] |
21 | print '10X98765432' [ sum ( map ( lambda x: int (x[ 0 ]) * x[ 1 ], zip (s[ 0 : 17 ], [ 7 , 9 , 10 , 5 , 8 , 4 , 2 , 1 , 6 , 3 , 7 , 9 , 10 , 5 , 8 , 4 , 2 ]) )) % 11 ] |
可能不熟悉Python的还看不懂怎么zip、map和reduce的作用,我再解释下吧。(sum太简单了,就不说了,相当于reduce的简化版。)
zip是迭代各个参数,并返回一个元组的列表。第i个元组由参数的第i个元素组成。当一个参数迭代完成后,就结束zip,其余参数未迭代的部分忽略。
举例来说:
04 | [( 1 , 4 ), ( 2 , 5 ), ( 3 , 6 )] |
05 | >>> zip ([ 1 , 2 ], * [( 3 , 4 ), ( 5 , 6 )]) |
07 | >>> (x, y) = zip ( * zip (a, b)) |
14 | [( 1 , 7 ), ( 2 , 8 ), ( 3 , 9 )] |
16 | [( 1 , 4 , 7 ), ( 2 , 5 , 8 ), ( 3 , 6 , 9 )] |
17 | >>> d = 'abcd' >>> zip (c, d) |
18 | [( 7 , 'a' ), ( 8 , 'b' ), ( 9 , 'c' ), ( 10 , 'd' )] |
map则是将一个函数迭代处理各个参数,返回结果列表。与zip不同的是,如果有个参数比较短,迭代完它后将用None来代替不足的元素,如果None不支持该操作,可能会抛出异常。
演示:
01 | >>> map ( lambda x: 2 * x, [ 1 , 2 , 3 ]) |
03 | >>> map ( lambda x: x[ 0 ] + x[ 1 ], [( 1 , 4 ), ( 2 , 5 ), ( 3 , 6 )]) |
05 | >>> map ( lambda x, y: x + y, [ 1 , 2 , 3 ], [ 4 , 5 , 6 ]) |
07 | >>> map ( lambda x, y: x + y, [ 1 , 2 , 3 ], [ 4 , 5 , 6 , 7 ]) |
08 | Traceback (most recent call last): |
09 | File "<stdin>" , line 1 , in <module> |
10 | File "<stdin>" , line 1 , in < lambda > |
11 | TypeError: unsupported operand type (s) for + : 'NoneType' and 'int' |
reduce是用一个函数从左至右依次迭代处理各个元素,并返回最后的总结果。此外,如果有第3个参数的话,会将第3个参数当成初始值。
01 | >>> reduce ( lambda x, y: x + y, [ 1 , 2 , 3 , 4 , 5 ]) |
03 | >>> reduce ( lambda x, y: x + y, range ( 101 )) |
05 | >>> reduce ( lambda x, y: x * y, range ( 1 , 11 )) |
07 | >>> print reduce ( lambda x, y: str (x) + str (y), range ( 11 ), '输出1~10: ' ) |
09 | >>> print reduce ( lambda x, y: (x + '%d' ) % y, range ( 11 ), '输出0~10: ' ) |
11 | >>> print ( lambda n, m: reduce ( lambda x, y: x + n * * y, xrange (m + 1 )))( 3 , 4 ) |
13 | >>> ( lambda n: reduce ( lambda x, y: x * y, xrange ( 1 , n + 1 )))( 10 ) |
Python果然是非常方便的东西啊~
========== 我是分割线 =============
PS:原文的 URL 中带中文,在原文链接中无法给全,特此注明。引用自这里。