出场人物介绍
小美:小学4年级学生,参加了学校的编程兴趣小组,已经了解了Python语言的基本语法,能够看懂一些简单的程序。她做事风风火火,对所有的事情都很好奇,喜欢打破砂锅问到底,是一个叫人又爱又恨的小丫头。
阿福:一个酷爱编程的8年级男生。大家都说他长得像国宝大熊猫,动作缓慢,憨态可掬。他做事情确实够慢的,连说话也慢条斯理,可是他一点也不担心,他常常说:“慢就是快,只要坚持下去,蜗牛也能爬上金字塔。”
古老师:虽然年近不惑,但依然对生活充满热情。“爱生活爱运动”是他的人生信条,和孩子们一起编程是他最大的乐趣。他神出鬼没,总是在孩子们最需要帮助的时候出现。当然,你也不能动不动就找古老师,因为他很忙,非常非常忙。所以,遇到问题还是自己先思考吧。
“Python算法之旅”微信群等着你
扫码加入“Python算法之旅”微信群,和斌哥面对面交流,更多资料和更有趣的话题等你一起来分享。
正文
字符串游戏之无效的身份证
小美:阿福,上次古老师留下的检验身份证号问题,你找到答案了吗?
阿福:找到了。身份证最后一位是根据前面十七位数字码,按照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。
例如,如果余数是0,身份证的第18位数字就是1;如果余数是2,身份证的最后一位号码就是罗马数字X。
小美:原来是这样。那你上次在示例2中给出的身份证号“33028110310641”,是先将前17位数字和系数相乘的结果相加,即3*7+3*9+0*10+2*5+8*8+1*4+2*2+0*1+1*6+0*3+1*7+0*9+3*10+1*5+0*8+6*4+4*2 = 210,再将210对11求余数,结果为1。所以,身份证号最后一位数字应该是0。
阿福:没错。既然你已经知道了检验的原理,那你能不能设计一个函数,根据输入的18位身份证号码,判断该身份证是否为有效身份证呢?
小美:这有什么难的!看我的。
问题1
函数功能:根据输入的18位身份证号码,判断该身份证是否为有效身份证。
函数名:check_id_num(id_num: str) -> bool
参数表:id_num -- 存储了18位身份证号码的字符串。
返回值:如果是有效身份证号返回True,否则返回False。
示例1:输入id_num='33028105302813',返回True
示例2:输入id_num='33028110310641',返回False
代码1
def check_id_num(id_num): factor = (7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2) #校验码系数 remainder = '10X98765432' #余数表 s = 0 for i in range(len(factor)):s+=factor[i]*int(id_num[i]) r = s % 11 return remainder[s%11] == id_num[-1]
古老师:小美进步很大啊!函数已经写得有模有样了。对了,阿福,你听说过map()函数吗?阿福:知道啊,map()函数是一个高阶函数,它接收两个参数,一个是函数,一个是迭代器(可迭代对象),map将传入的函数依次作用到序列的每个元素,并把结果作为新的迭代器返回。
例如我们有一个函数f(x) = x * x,把该函数作用在一个列表[1, 2, 3, 4, 5, 6]上,就可以用map()实现如下:
代码2
def f(x): return x * xa = list(map(f, [1, 2, 3, 4, 5, 6]))
这样就可以得到列表a = [1, 4, 9, 16, 25, 36]。古老师:不错,知识点记得挺牢啊!那你知道匿名函数吗?能不能把上面的语句用匿名函数表示?阿福:可以,这样只需要一条语句就够了:
代码3
a = list(map(lambda x: x * x, [1, 2, 3, 4, 5, 6]))
知识小贴士
python 使用 lambda 来创建匿名函数。所谓匿名,意即不再使用 def 语句这样标准的形式定义一个函数。lambda的主体是一个表达式,而不是一个代码块,它的语法只包含一个语句,如下:lambda [arg1 [,arg2,.....argn]]:expression
古老师:没错。那你现在再看看小美写的check_id_num()函数,能不能使用map()函数来表达呢?
阿福:这个。。。。。。我明白了!可以先使用map()函数生成一个新的序列,再使用内置函数sum()对序列求和,这样可以用一条赋值语句代替原来的for循环。
代码4
def check_id_num(id_num): factor = (7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2) #校验码系数 remainder = '10X98765432' #余数表 s = sum(map(lambda x, y: x * int(y), factor, id_num)) return remainder[s%11] == id_num[-1]
古老师:不错不错!看来你已经领会到map()函数的精髓了。继续努力,迎接更大的挑战。今天就到这吧,下次有事记得叫我。
温馨提示:
有事没事最好拉到文末看看,说不定作者今天提供了彩蛋哦!
说在后面
Python算法之旅系列文章源于我平时收集和整理的一些题目,我尝试用自己的语言把这些题目进行了再创作。由于本人水平有限,表述中难免出现疏漏甚至错误之处,敬请谅解。
无论是赞同还是反对我的看法,都请你给我留言。如果你有新的想法,千万不要憋在心里,请发出来大家一起讨论。让我们相互学习,共同进步!
需要本文word版的,可以加入“Python算法之旅”知识星球参与讨论和下载文件,“Python算法之旅”知识星球汇集了数量众多的同好,更多有趣的话题在这里讨论,更多有用的资料在这里分享。
我们专注Python算法,感兴趣就一起来!
彩蛋
除了使用map()函数生成一个新的序列,我们还可以用列表生成器来生成新序列,然后使用sum()函数对序列求和。
代码5
def check_id_num(id_num): factor = (7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2) #校验码系数 remainder = '10X98765432' #余数表 s = sum([factor[i] * int(id_num[i]) for i in range(len(factor))]) r = s % 11 return remainder[s%11] == id_num[-1]
相关优秀文章:
阅读代码和写更好的代码
最有效的学习方式
字符串游戏之身份证号的秘密