Python-递归讨论

学习编程,应该是介于学习游泳和学习外语(比如英语)之间的一件事,我是从方法这个角度来阐述这个问题的。游泳,是典型的实践性学习,你学习再多的游泳知识,背诵再多的口诀,都不能让你跳进水里,立马开始畅游其中。我儿子很小的时候,就是这么想的,在3-5岁时吧,一次到水上中心玩耍,(因为那里的水不深,也就没太在意)结果他很勇敢的就跳进了水里,试图像电视中看到的那样,畅游一番,结果可想而知,呛了几口水,便站起来不敢动了。(顺便说一下,他现在是程序员,比我水平高一点而已);而学习英语,基本就是语法词汇等等,主要是记忆方面的事情,是典型的学习,但也是有自己的门道,比如口语,你不练习,试图张口就来流利的英语,肯定没门。还有,想当年全国流行学习英语时,有不少人,是认为只要搞懂了语法,一切都会迎刃而解的,专门重点攻读语法。还有更牛的,(的确很牛,因为这类人是观察能力极强又有着天然的质疑癖好的),竟然认为英语的某种语法(比如第三人称)不符合逻辑云云,自然,是不会学好英语的,因为他抗拒这些不符合逻辑的事情。

而编程貌似介于两者其中,既要记忆学习一些语法规则,但大量的还是实践编程,到了项目阶段,就不单纯是代码的事情,而是如何将现实用代码表达出来,有些功夫在诗外的意思了。

啰嗦上面那些,是希望你不断的练习敲代码,然后运行,分析,总结。很快,一般的几个月就有些成就感了。其实不少人是在学习了几个月后,就成了程序员,并且高薪了。好了,down to the business.

如果你第一次遇见递归,递归函数,能够轻松理解,你不是天才也是准天才,请一定通知我,我会隆重推荐你的。当然,如果从一开始就仔细研读递归的解释,你也会很快成为牛X起来的。

先举例,后解释,最后总结。看代码:

解释:

阶乘是一些连续自然数的相乘,比如:5*4*3*2*1是5的阶乘。

“”“ “””,3个引号之间的内容被称为文档字符串,将来你牛了,写的函数被别人使用,你这些字符串,他人就能在help()下看到,所以,要写的很清楚才好。

我在作者代码的基础上加了几个print,后面的#解释了这么做的原因,你也要多多模仿,尽量使用#来解释代码,当你的代码需要其他人阅读时。这几个print很好的帮助了我们来理解代码运行中的过程,顺便说一句,编辑器应该都带有断点功能,可以调试代码并观察其运行。

作者称,第二段代码比第一段代码看起来更像递归,我们也是这么考虑的。第一段代码说它是循环也当然正确。所以,循环和递归应该是本质一样的吧。

在函数内部调用函数自己,这就是递归的思想体现。有的人可能认为有点奇怪,自己能调用自己,是的,能,这就是设计者们这么设计的。好像我见过的所有编程语言都有递归函数。

具体的,factI 很明显,每次循环都把参数 n 减少 1,所有到了等于 1 的时候就结束循环了。factR好像不明显,何时结束循环,要知道factR是持续展开的,上面的return里面,factR(n-1), 只要 n-1 不等于 1,他就持续展开,搞张纸,自己展开一下看看。到了(n-1)等于1的时候就结束了展开,开始计算了。这个需要反复在纸上操练,才能真正掌握,如果你会使用更多的print,自然在代码里面也能演示。

你还没有彻底弄懂?没关系,来一个更难的,逼你就范。斐波那契数,历史由来,大家可以网上搜。只要知道,他是一系列数(好像整数才行,又好像是从0和1开始的,不确定),其中的任一个数字都是前两个数字之和。很显然,前两个数字是基础条件,递归的条件,因为前两个数字无法适用前两个数字之和这个规则。作者强调说,这个基础案例(case)可以有任意多个。看代码:

不再解释,只提示:

第3行 or 相当于 或者的逻辑用语。

当第5行到了fib(n-1)时,其实就是调用fib函数,所以他必然展开。

testFib 是测试函数,这个是个很好的或者说必须的一步,就是对自己定义的函数测试,从而确保函数运转正常,并适合所有值。并且这个testFib函数把过程也展示出来了。

range是个内置函数,要继续使用help(range)来学习它。英语的,没有关系,看懂看不懂的,从上到下看看,总是有收获的。

汉诺塔,是的,我们明天讲解著名的汉诺塔,学会了自己写汉诺塔的代码,就算是递归灵活掌握了。

明天再见。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20190120G08TU000?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。

扫码关注云+社区

领取腾讯云代金券

年度创作总结 领取年终奖励