diff --git a/Answer_Lab01-08.ipynb b/Answer_Lab01-08.ipynb new file mode 100644 index 0000000..57faacb --- /dev/null +++ b/Answer_Lab01-08.ipynb @@ -0,0 +1,1601 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "b57930d5", + "metadata": {}, + "source": [ + "## 实践1 初识Python " + ] + }, + { + "cell_type": "markdown", + "id": "b734eb0e", + "metadata": {}, + "source": [ + "(1)使用for语句改写下面程序,实现一下输出。\n", + "重要的事情说三遍\n", + "Hello Python World!\n", + "Hello Python World!\n", + "Hello Python World!" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "id": "beba0cb8", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Hello Python World!\n", + "Hello Python World!\n", + "Hello Python World!\n" + ] + } + ], + "source": [ + "for i in range(3):\n", + " print(\"Hello Python World!\")" + ] + }, + { + "cell_type": "raw", + "id": "13c70a11", + "metadata": {}, + "source": [ + "(2)改写程序Fl1-2,实现求任意两个整数的乘积并输出\n", + " 要求:增加变量a和b,表示乘法运算的2个操作数,改写乘法的表达式。\n", + " a变量和b变量的值由用户输入,输入两个整数。\n" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "id": "1c59a977", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "a=10\n", + "b=50\n", + "500\n" + ] + } + ], + "source": [ + "a=int(input(\"a=\"))\n", + "b=int(input(\"b=\"))\n", + "s =a* b\n", + "print(s)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ef6056cb", + "metadata": {}, + "outputs": [], + "source": [ + "(3)改写程序FL1-3.py,实现输入一个月份,输出对应的英文缩写" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "id": "e06373bd", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "month=7\n", + "Jul\n" + ] + } + ], + "source": [ + "months=\"MonFebMarAprMayJunJulAugSepOctNovDec\" \n", + "n = int(input(\"month=\"))\n", + "monthAbbrev = months[(n-1)*3:(n-1)*3+3]\n", + "print(monthAbbrev)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "053250c7", + "metadata": {}, + "outputs": [], + "source": [ + "(4)改写程序FL1-3.py,实现顺序输出12月份对应的英文缩写。" + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "id": "dee2c400", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Mon\n", + "Feb\n", + "Mar\n", + "Apr\n", + "May\n", + "Jun\n", + "Jul\n", + "Aug\n", + "Sep\n", + "Oct\n", + "Nov\n", + "Dec\n" + ] + } + ], + "source": [ + "months=\"MonFebMarAprMayJunJulAugSepOctNovDec\" \n", + "for n in range(1,13):\n", + " monthAbbrev = months[(n-1)*3:(n-1)*3+3]\n", + " print(monthAbbrev)" + ] + }, + { + "cell_type": "markdown", + "id": "9bf6e1a2", + "metadata": {}, + "source": [ + "## 实践2 Python 基本语法" + ] + }, + { + "cell_type": "markdown", + "id": "b0d77cb9", + "metadata": {}, + "source": [ + "1.输入以下表达式并查看结果。\n", + "\n", + "①23+3 ②23>3 ③'23'+'3' ④23/3 ⑤ 23//3⑥23%3⑦23**3 \n", + "问题:\n", + "表达式结果为整数类型有哪些? ①⑤ ⑥⑦\n", + "表达式结果为浮点数类型有哪些?④\n", + "表达式结果为字符串类型有哪些? ③ \n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "dffd4966", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "id": "7e403538", + "metadata": {}, + "source": [ + "2.执行完下面数值表达式语句后,变量a~k的值分别是多少?\n", + "```python \n", + "a=5\n", + "b=2\n", + "a*=b\n", + "b+=a\n", + "a,b=b,a\n", + "c=6\n", + "d= c%2+(c+1)%2\n", + "e =2.5\n", + "f=3.5\n", + "g=(a+b)%3+int(f)//int(e)\n", + "h=float(a+b)%3+int(f)//int(e)\n", + "i=(a+b)/3+f%e\n", + "j=a 10 or x < -10:\n", + " print(\"ERROR\")\n", + "else:\n", + " if x < 0:\n", + " y = 2 * x * x * x + 4 * x * x + 3\n", + " elif x < 6:\n", + " y = x + 14\n", + " else : #2\n", + " y = 6 * x \n", + " print(y) #3" + ] + }, + { + "cell_type": "markdown", + "id": "41287cfc", + "metadata": {}, + "source": [ + "## 实践5 小试身手\n", + "1.使用while语句编写程序,输入一个小于等于12的整数n,逐个输出字符串 '人生苦短我用python' 中前n个字符。 \n", + "例如 \n", + "输入:4 输出:人生苦短 \n", + "提示: \n", + "(1)s[i]表示s中第i+1个字符; \n", + "(2)print(...,end=\"\")可以不换行。 " + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "1cf553c3", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "4\n", + "人生苦短" + ] + } + ], + "source": [ + "n=int(input())\n", + "s = '人生苦短我用python'\n", + "i=0\n", + "while( i0:\n", + " s1=s1+x\n", + " n1=n1+1\n", + " elif x<0:\n", + " s2=s2+x\n", + " n2=n2+1\n", + " x=input(\"请输入一个浮点数:\")\n", + "print(\"{}个正数的平均值为:{:.2f} \".format(n1,s1/n1))\n", + "print(\"{}个负数的平均值为:{:.2f} \".format(n2,s2/n2))\n" + ] + }, + { + "cell_type": "markdown", + "id": "3822336a", + "metadata": {}, + "source": [ + "3.使用random模块函数,随机生成100个值为【-1000,1000】之间的整数,分别统计其中能被3或7整除的数的个数。" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "28fc250e", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "511\t720\t-717\t-468\t780\t-198\t\n", + "能被3或7整除的数有6个,均值为104.66666666666667\n" + ] + } + ], + "source": [ + "from random import randint \n", + "n = 0\n", + "s = 0\n", + "for i in range(20):\n", + " x = randint(-1000,1000)\n", + " if x%3 == 0 or x%7 == 0:\n", + " print(x,end=\"\\t\")\n", + " s += x\n", + " n = n+1\n", + "print(f\"\\n能被3或7整除的数有{n}个,均值为{s/n}\")\n", + " " + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "f966e03c", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "-63" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "s\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "85940ae3", + "metadata": {}, + "outputs": [], + "source": [ + "4.:输入一组数,寻找最大值,需要同时输出,最大值的第几个数,如何修改程序?" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "117cd534", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "请输入一个浮点数:9.34\n", + "请输入一个浮点数:-0.25\n", + "请输入一个浮点数:190.382\n", + "请输入一个浮点数:88.27\n", + "请输入一个浮点数:-82.99\n", + "请输入一个浮点数:over\n", + "最大值是第3个数190.382\n" + ] + } + ], + "source": [ + "maxnum=input(\"请输入一个浮点数:\")\n", + "maxindex=1\n", + "n=1\n", + "if maxnum != \"over\":\n", + " maxnum=float(maxnum)\n", + " \n", + " x=input(\"请输入一个浮点数:\")\n", + " n=2\n", + " while x!=\"over\":\n", + " x=float(x)\n", + " if x > maxnum:\n", + " maxnum=x\n", + " maxindex=n\n", + " \n", + " x=input(\"请输入一个浮点数:\")\n", + " n=n+1\n", + "\n", + " print(f\"最大值是第{maxindex}个数{maxnum}\")\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "72db5e68", + "metadata": {}, + "outputs": [], + "source": [ + "打出所有的水仙花数(水仙花数是指一个 3 位数,它的每个位上的数字的 3次幂之和等于它本身)" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "018fad85", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "153\t370\t371\t407\t" + ] + } + ], + "source": [ + "for a in range(1,10):\n", + " for b in range(0,10):\n", + " for c in range(0,10):\n", + " num=a*100+b*10+c\n", + " if a**3+b**3+c**3 == num:\n", + " print(num,end=\"\\t\")\n", + " " + ] + }, + { + "cell_type": "markdown", + "id": "b4f0c3fa", + "metadata": {}, + "source": [ + "## 实践8" + ] + }, + { + "cell_type": "markdown", + "id": "93362a6e", + "metadata": {}, + "source": [ + "### 试一试\n", + "\n", + "利用s1、s2和字符串操作,写出能产生下列结果的表达式。\n", + "s1='programming'\n", + "s2='language'\n", + "(1)\"program\" \n", + "(2)\"prolan\" \t\n", + "(3)\"amamam\"\n", + "(4)\" programming language \"\n", + "(5)\"progr@mming l@ngu@ge\"\n" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "0c326a7d", + "metadata": {}, + "outputs": [], + "source": [ + "s1='programming'\n", + "s2='language'" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "57e9ecb1", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'program'" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "#(1)\"program\"\n", + "s1[:7]" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "f3665008", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'prolan'" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "#(2)\"prolan\" \n", + "s1[:3]+s2[:3]" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "e32b93e1", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'amamam'" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "#(3)\"amamam\"\n", + "s1[5:7]*3" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "67c7c983", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'progr@mming l@ngu@ge'" + ] + }, + "execution_count": 22, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "#(4)\"progr@mming l@ngu@ge\"\n", + "s1.replace(\"a\",\"@\")+\" \"+s2.replace(\"a\",\"@\")" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "7c06cdb5", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'Programming Language'" + ] + }, + "execution_count": 23, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "#(5)'Programming Language'\n", + "s1.capitalize()+\" \"+s2.capitalize()" + ] + }, + { + "cell_type": "markdown", + "id": "111debcc", + "metadata": {}, + "source": [ + "### 试一试:\n", + "寻找一个源字符串s中的子串sub的所有位置。" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "82a651ae", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "s=do not,for one repuls,forgo the purpose that you resolved to effort\n", + "sub=o\n", + "1\t4\t8\t11\t23\t26\t36\t46\t52\t59\t64\tover\n" + ] + } + ], + "source": [ + "#方法一 经典while循环\n", + "s = input(\"s=\")\n", + "sub = input(\"sub=\")\n", + "start=0\n", + "index=s.find(sub,start)\n", + "while index != -1:\n", + " print(index,end=\"\\t\")\n", + " start = index+1\n", + " index=s.find(sub,start)\n", + "print(\"over\")\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "728ce498", + "metadata": {}, + "outputs": [], + "source": [ + "#方法二 while True 算法模式\n", + "s = input(\"s=\")\n", + "sub = input(\"sub=\")\n", + "start=0\n", + "\n", + "while True:\n", + " index=s.find(sub,start)\n", + " if index == -1:\n", + " break\n", + " print(index,end=\"\\t\")\n", + " start = index+1\n", + " \n", + "print(\"over\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e35a0a52", + "metadata": {}, + "outputs": [], + "source": [ + "方法三 异常处理算法模式\n", + "s = input(\"s=\")\n", + "sub = input(\"sub=\")\n", + "start = 0\n", + "while True:\n", + " try:\n", + " index=s.index(sub,start)\n", + " print(index,end=\"\\t\")\n", + " start=index+1\n", + " except ValueError:\n", + " print('over')\n", + " break\n" + ] + }, + { + "cell_type": "markdown", + "id": "42ccd924", + "metadata": {}, + "source": [ + "### 小试身手 \n" + ] + }, + { + "cell_type": "markdown", + "id": "f89f066b", + "metadata": {}, + "source": [ + "(1)编写程序 实现二进制IP地址转为十进制IP地址。 \n", + "一个IP地址是由四个字节(每个字节8个位)的二进制码组成。输入一个合法的二进制表示的IP地址,请将其转换为十进制格式表示的IP地址输出(不考虑异常输入数据)。 \n", + "运行示例: \n", + "input:11001100100101000001010101110010 \n", + "output:204.148.21.114 " + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "id": "a284705c", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "11001100100101000001010101110010\n", + "204.148.21.114\n" + ] + } + ], + "source": [ + "ip2=input()\n", + "ip10=\"\"\n", + "start=0\n", + "for i in range(4):\n", + " x=int(ip2[start:start+8],2)\n", + " ip10+=str(x)+\".\"\n", + " start+=8\n", + "print(ip10[:-1])\n" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "id": "5ec84a36", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "11001100100101000001010101110010\n", + "204.148.21.114\n" + ] + } + ], + "source": [ + "ip2=input()\n", + "print(str(int(ip2[0:8],2))+\".\"+str(int(ip2[8:16],2))+\".\"+str(int(ip2[16:24],2))+\".\"+str(int(ip2[24:],2)))\n" + ] + }, + { + "cell_type": "markdown", + "id": "be7b2b8c", + "metadata": {}, + "source": [ + "(2)编写程序 随机产生50个-1000~1000之间的整数,输出其中逆序数大于原数据的整数并统计个数。 " + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "id": "d7ce4f17", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "687 -564 -662 -873 519 367 -625 375 436 -981 -742 -231 -671 -382 -32 -30 -958 -920 -520 -97 -350 69 29 \n", + "共23个数\n" + ] + } + ], + "source": [ + "from random import randint\n", + "n=0\n", + "for i in range(50):\n", + " x = randint(-1000,1000)\n", + " if x>0:\n", + " y = int(str(x)[::-1])\n", + " else:\n", + " y = int(str(x)[:0:-1])*-1\n", + " if y>x:\n", + " print(x,end=\" \")\n", + " n=n+1\n", + "print(f\"\\n共{n}个数\")\n" + ] + }, + { + "cell_type": "markdown", + "id": "531bc39c", + "metadata": {}, + "source": [ + "(3)编写程序 实现电文加密 \n", + "有一行电文,已按如下规律译成密码: \n", + "A-->Z a-->z \n", + "B-->Y b-->y \n", + "C-->X c-->x \n", + " ...... ...... \n", + "即第一个字母变成第26个字母,第i个字母变成第(26-i+1)个字母,非字母字符不变。要求根据密码译回原文,并输出。 \n", + "\n", + "运行示例 \n", + "input:ABC123abc \n", + "output:ZYX123zyx \n", + "\n", + "\n", + "input:Life is like an ice cream, enjoy it before it melts. \n", + "output:Oruv rh orpv zm rxv xivzn, vmqlb rg yvuliv rg nvogh. \n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 45, + "id": "8e3012c9", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Life is like an ice cream, enjoy it before it melts.\n", + "Oruv rh orpv zm rxv xivzn, vmqlb rg yvuliv rg nvogh.\n" + ] + } + ], + "source": [ + "plaintext = input()\n", + "ciphertext = ''\n", + "for ch in plaintext:\n", + " if ch.isupper():\n", + " ciphertext += chr(ord(\"A\")+26-(ord(ch)-ord(\"A\"))-1)\n", + " elif ch.islower():\n", + " ciphertext += chr(ord(\"a\")+26-(ord(ch)-ord(\"a\"))-1)\n", + " else:\n", + " ciphertext = ciphertext + ch\n", + "print(ciphertext)" + ] + }, + { + "cell_type": "code", + "execution_count": 52, + "id": "345f93b6", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Life is like an ice cream, enjoy it before it melts.\n", + "Oruv rh orpv zm rxv xivzn, vmqlb rg yvuliv rg nvogh.\n" + ] + } + ], + "source": [ + "import string \n", + "\n", + "plaintext = input()\n", + "ciphertext = ''\n", + "lower = string.ascii_lowercase\n", + "upper = string.ascii_uppercase \n", + "for ch in plaintext:\n", + " if ch in low:\n", + " ciphertext += low[26-low.find(ch)-1]\n", + " elif ch in upper:\n", + " ciphertext += upper[26-upper.find(ch)-1]\n", + " else:\n", + " ciphertext = ciphertext + ch\n", + "print(ciphertext) \n", + " \n", + " " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8c421a43", + "metadata": {}, + "outputs": [], + "source": [ + "\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1e224ed4", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.10" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/Answer_Lab09-13.ipynb b/Answer_Lab09-13.ipynb new file mode 100644 index 0000000..3873ca6 --- /dev/null +++ b/Answer_Lab09-13.ipynb @@ -0,0 +1,962 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "2b789064", + "metadata": {}, + "source": [ + "# 实验9~实践12 参考答案" + ] + }, + { + "cell_type": "markdown", + "id": "e1fa4e6d", + "metadata": {}, + "source": [ + "## 实践9 元组和列表 \n" + ] + }, + { + "cell_type": "markdown", + "id": "d6b5ae4e", + "metadata": {}, + "source": [ + "### 小试身手1\n", + "(1)\t已知列表 L1 和L2,由 L1 和 L2 构造L3,并回答问题。 \n", + "```python\n", + " >>> L1=[1,2,3,4,5]\n", + " >>> L2=[\"one\",\"two\",\"three\",\"four\",\"five\"]\n", + " >>> L3=[[L1[1],L2[1]],[L1[2],L2[2]],[L1[3],L2[3]]]\n", + "L3 的值是__________\n", + "L3[1][1]的值是__________\n", + "执行 L4=L3.pop(2)后,列表L3的值是__________,L4的值是__________。\n", + "再执行L3.extend(L4),列表L3的值是__________。\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "ee0db3a0", + "metadata": {}, + "outputs": [], + "source": [ + "L1=[1,2,3,4,5]\n", + "L2=[\"one\",\"two\",\"three\",\"four\",\"five\"]\n" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "61ec7df3", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[[2, 'two'], [3, 'three'], [4, 'four']]" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "L3=[[L1[1],L2[1]],[L1[2],L2[2]],[L1[3],L2[3]]]\n", + "L3" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "873f2572", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'three'" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "L3[1][1]" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "d3ca6442", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[4, 'four']" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "L4=L3.pop(2)\n", + "L4" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "7910a864", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[[2, 'two'], [3, 'three'], 4, 'four']" + ] + }, + "execution_count": 20, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "L3" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "f2a4aaa7", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[[2, 'two'], [3, 'three'], 4, 'four']" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "L3.extend(L4)\n", + "L3" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a6e368db", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "id": "de8197bc", + "metadata": {}, + "source": [ + "(2)假设执行了如下语句\n", + "```python\n", + ">>> s1=[0,1,2,3,4,5,6]\n", + ">>> s2=['SUN','MON','TUE','WED','THU','FRI','SAT']\n", + "利用 s1、s2 和列表操作,创建下列结果的序列对象。\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "d985454f", + "metadata": {}, + "outputs": [], + "source": [ + "s1=[0,1,2,3,4,5,6]\n", + "s2=['SUN','MON','TUE','WED','THU','FRI','SAT']" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "a5a002be", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'SUN|MON|TUE|WED|THU|FRI|SAT'" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "#s3: 'SUN|MON|TUE|WED|THU|FRI|SAT'\n", + "s3=\"|\".join(s2)\n", + "s3" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "f8bb4c02", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[3, 4, 3, 4, 3, 4]" + ] + }, + "execution_count": 21, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "#s4:[3,4,3,4,3,4]\n", + "s4=s1[3:5]*3\n", + "s4" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "bea9fa4d", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[(0, 'SUN'), (1, 'MON'), (2, 'TUE'), (3, 'WED'), (4, 'THU'), (5, 'FRI'), (6, 'SAT')]\n" + ] + } + ], + "source": [ + "#s5: [(0,'SUN'),(1,'MON'),(2,'TUE'),(3,'WED'),(4,'THU'),(5,'FRI'),(6,'SAT')]\n", + "s5=list(zip(s1,s2))\n", + "print(s5)" + ] + }, + { + "cell_type": "markdown", + "id": "b7e2a784", + "metadata": {}, + "source": [ + "## 小试身手2\n", + "### (1)合并列表 \n", + "使用随机函数randint(),建立两个长度为5的二维列表A和B。包含的数据如下:‪‬‪‬‪‬‪‬‪‬‮‬‫‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‭‬\n", + "\n", + "A列表:包含子列表 [学号,p成绩,m成绩],学号为从1开始递增的正整数,成绩为0-100之间的随机整数。‪‬‪‬‪‬‪‬‪‬‮‬‫‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‭‬\n", + "\n", + "B列表:包含子列表 [学号,q成绩],学号为从1开始递增的正整数,成绩为0-100之间的随机整数‪‬‪‬‪‬‪‬‪‬‮‬‫‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‭‬\n", + "\n", + "先需要将A,B两个列表数据进行合并,即将B列表中的‘q成绩’添加到A列表中的相同学号的子列表中。‪‬‪‬‪‬‪‬‪‬‮‬‫‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‭‬\n", + "\n", + "输入一个整数k,将B列表中的'q成绩'插入到A列表相同学号的子列表的k位置上。‪‬‪‬‪‬‪‬‪‬‮‬‫‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‭‬\n", + "\n", + "合并完成后,输出合并后的A列表。‪‬‪‬‪‬‪‬‪‬‮‬‫‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‭‬\n", + "\n", + "注意:为保证生成固定序列,本题需要使用同一个循环结构生成两个随机列表A和B,类似:\n", + "```python\n", + "for #######:\n", + " #A列表添加 学号,p成绩,m成绩\n", + " #B列表添加 学号,q成绩\n", + "运行示例:\n", + "A: [[1, 94, 58], [2, 6, 84], [3, 26, 42], [4, 39, 98], [5, 22, 18]]\n", + "B: [[1, 33], [2, 82], [3, 29], [4, 26], [5, 24]]\n", + "3\n", + "[[1, 94, 58, 33], [2, 6, 84, 82], [3, 26, 42, 29], [4, 39, 98, 26], [5, 22, 18, 24]]\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c4adadb0", + "metadata": {}, + "outputs": [], + "source": [ + "import random\n", + "a=[]\n", + "b=[]\n", + "\n", + "for i in range(1,6): \n", + " a.append([i,random.randint(0,100),random.randint(0,100)]) \n", + " b.append([i,random.randint(0,100)])\n", + "print(\"A:\",a)\n", + "print(\"B:\",b)\n", + "p=int(input()) \n", + "for i in range(len(a)):\n", + " a[i].insert(p,b[i][1]) \n", + "print(a) " + ] + }, + { + "cell_type": "markdown", + "id": "f9dd4a7a", + "metadata": {}, + "source": [ + "### (2)成绩统计\n", + "输入用空格分隔的两个正整数n和m,表示后面要接收m个人的n门课的成绩的输入。\n", + "随后的m行,每行输入用空格分隔的n个成绩。题目保证m和n都在(0-100]之间。\n", + "请统计\n", + "(1)每门课的平均成绩。\n", + "(2)每个学生的平均成绩\n", + "(3)每门课的最高分" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "id": "23a32ac5", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "n=3\n", + "m=5\n", + "63 87 76\n", + "98 92 90\n", + "86 83 82\n", + "69 98 71\n", + "77 74 92\n", + "[[63, 87, 76], [98, 92, 90], [86, 83, 82], [69, 98, 71], [77, 74, 92]]\n", + "每个学生的平均成绩: [75.33, 93.33, 83.67, 79.33, 81.0]\n", + "每门课的平均成绩: [78.6, 86.8, 82.2]\n", + "每门课的最高分: [98, 98, 92]\n" + ] + } + ], + "source": [ + "n,m = int(input(\"n=\")),int(input(\"m=\"))\n", + "Scores = []\n", + "for i in range(m):\n", + " Scores.append([int(x) for x in input().split()])\n", + "print(Scores)\n", + "avgs=[]#每个学生的平均成绩\n", + "for stu in Scores:\n", + " avgs.append(round(sum(stu)/len(stu),2))\n", + "print(\"每个学生的平均成绩:\",avgs)\n", + "\n", + "ksums=[0]*n #每门课的平均成绩\n", + "kmaxs=[0]*n #每门课的最高分\n", + "for stu in Scores:\n", + " for i in range(n):\n", + " ksums[i]+=stu[i]\n", + " if stu[i]>kmaxs[i]:\n", + " kmaxs[i] = stu[i]\n", + "kavgs = [ round(x/m,2) for x in ksums]\n", + "print(\"每门课的平均成绩:\",kavgs)\n", + "print(\"每门课的最高分:\",kmaxs)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "84af1780", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "id": "5262941a", + "metadata": {}, + "source": [ + "## 实践10 集合和字典\n", + "小试身手1 (略)" + ] + }, + { + "cell_type": "markdown", + "id": "471a3f13", + "metadata": {}, + "source": [ + "### 小试身手2\n", + "输入两个整数,在这两个整数组成的闭区间范围内生成100个随机整数,并统计出现数据的次数,按照生成随机数从小到大的顺序,每行输出一个生成的整数以及其出现的次数,以空格间隔。 \n", + "```python\n", + "例如:\n", + "输入:\n", + "3 5\n", + "输出:\n", + "3 36\n", + "4 39\n", + "5 25\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "id": "c82977a4", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "3 5\n", + "3 36\n", + "4 39\n", + "5 25\n" + ] + } + ], + "source": [ + "import random\n", + "dic = {}\n", + "m,n=map(int,input().split())\n", + "random.seed(10)\n", + "\n", + "for i in range (100):\n", + " key = random.randint(m,n)\n", + " if key in dic:\n", + " dic[key] += 1\n", + " else:\n", + " dic[key] = 1\n", + "for i in sorted(dic.keys()):\n", + " print('{} {}'.format(i,dic[i]))" + ] + }, + { + "cell_type": "markdown", + "id": "9d5b06fc", + "metadata": {}, + "source": [ + "## 实践11 模块化程序设计 \n", + "1.完整程序,程序功能实现统计1000以内每100个整数中素数的个数。" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "dcba82ab", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " 1- 100 有26个素数\n", + "101- 200 有21个素数\n", + "201- 300 有16个素数\n", + "301- 400 有16个素数\n", + "401- 500 有17个素数\n", + "501- 600 有14个素数\n", + "601- 700 有16个素数\n", + "701- 800 有14个素数\n", + "801- 900 有15个素数\n", + "901-1000 有14个素数\n" + ] + } + ], + "source": [ + "from math import sqrt\n", + "def isPrime(n):\n", + " m=int(sqrt(n))\n", + " for i in range(2,m+1):\n", + " if n%i ==0:\n", + " return False\n", + " return True\n", + "def countPrimes(start,end):\n", + " c=0\n", + " for n in range(start,end+1):\n", + " if isPrime(n):\n", + " c=c+1\n", + " return c \n", + "\n", + "#主程序\n", + "for start in range(1,1000,100):\n", + " print(f\"{start:3d}-{start+99:4d} 有{countPrimes(start,start+99)}个素数\")\n", + " " + ] + }, + { + "cell_type": "markdown", + "id": "e33847ab", + "metadata": {}, + "source": [ + " ## 3.斐波那契数列\n", + " ### (1) 单变量实现" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "efa91d0c", + "metadata": {}, + "outputs": [], + "source": [ + "def fib(n):\n", + " if n<=2:\n", + " return 1\n", + " f1=f2=1\n", + " while n>=3:\n", + " f3=f1+f2\n", + " f1,f2=f2,f3\n", + " n=n-1\n", + " return f3\n", + "\n", + "\n", + "n=int(input(\"n=\"))\n", + "print(fib(n))\n" + ] + }, + { + "cell_type": "markdown", + "id": "4d0b3b92", + "metadata": {}, + "source": [ + "## (2) 列表实现" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "48aa767e", + "metadata": {}, + "outputs": [], + "source": [ + "def fib( n ):\n", + " if n<=2:\n", + " return 1\n", + " FL=[1,1]\n", + " i=2\n", + " while i0:\n", + " print(value%10,end=\"\")\n", + " reverseDisplay(value//10)\n", + " return" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "cc25a415", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "12345" + ] + } + ], + "source": [ + "reverseDisplay(54321)" + ] + }, + { + "cell_type": "markdown", + "id": "0e80ecad", + "metadata": {}, + "source": [ + "3.使用递归方法逆序输出一个字符串中的字母 " + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "a2ff79ad", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "edcba" + ] + } + ], + "source": [ + "def reverseDisplay(s):\n", + " if len(s)!=1:\n", + " reverseDisplay(s[1:])\n", + " print(s[0],end=\"\")\n", + "reverseDisplay(\"abcde\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fcc70358", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.10" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/Lab11.ipynb b/Lab11.ipynb new file mode 100644 index 0000000..cacc4cf --- /dev/null +++ b/Lab11.ipynb @@ -0,0 +1,867 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# 实践11 程序的模块化编程 \n", + "模块化设计同样是程序设计的重要思想。程序的模块化设计,简单地说就是程序的编写不是一开始就逐条编写计算机语句和指令,而是首先用主程序、函数等框架把软件的主要结构和流程描述出来,并定义和调试好各个框架之间的输入、输出链接关系。再逐个实现每个模块的内部功能。模块化编程的目的是为了降低程序复杂度,使程序设计、调试和维护等操作简单化。 \n", + "1.理解程序的模块化设计方法 \n", + "2.理解参数和返回值的意义 \n", + "3.理解函数的执行过程 \n", + "4.掌握功能模块设计和实现 \n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 1. 画“工”字" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "【例4-2-1】用字符画一个“工”字。\n", + "程序的功能是输入一个n值,画出的“工”字由2根2n+1个“8”组成的横线和1根n个“8”组成的竖线构成。\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "n=int(input(\"n=\"))\n", + "for i in range(2*n+1):\n", + " print(\"8\",end=\"\")\n", + "print()\n", + "for i in range(n): \n", + " for j in range(n):\n", + " print(\" \",end=\"\")\n", + " print(\"8\")\n", + "for i in range(2*n+1):\n", + " print(\"8\",end=\"\")\n", + "print()\n" + ] + }, + { + "attachments": { + "image.png": { + "image/png": "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" + } + }, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "【例4-2-2】设计两个构件模块:画横线和画竖线,再设计一个图形模块:画“工”字。改写后的程序如下所示。\n", + "![image.png](attachment:image.png)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def hline(n):#画横线\n", + " for i in range(2*n+1):\n", + " print(\"8\",end=\"\")\n", + " print()\n", + "def vline(n):#画竖线\n", + " for i in range(n):\n", + " for j in range(n): \n", + " print(\" \",end=\"\")\n", + " print(\"8\")\n", + "def figure(n):#画“工”字\n", + " hline(n)\n", + " vline(n) \n", + " hline(n) \n", + "def draw():#画指定n值的“工”字\n", + " n=int(input(\"n=\"))\n", + " figure(n)\n", + "draw() #主程序启动 \n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "【例4-2-3】在例4-2-2的hline函数、vline函数、figure函数增加参数ch,传递用户输入的字符。" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def hline(n,ch):\n", + " for i in range(2*n+1):\n", + " print(ch,end=\"\")\n", + " print()\n", + "def vline(n,ch):\n", + " for i in range(n):\n", + " for j in range(n):\n", + " print(\" \",end=\"\")\n", + " print(ch)\n", + "def figure(n,ch):\n", + " hline(n,ch)\n", + " vline(n,ch) \n", + " hline(n,ch)\n", + " \n", + "def draw():\n", + " n=int(input(\"n=\"))\n", + " ch=input(\"ch=\")\n", + " figure(n,ch)\n", + "draw() \n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 程序的开发过程\n", + "\n", + "(1)自顶向下、逐步求精是分析问题的基本方法,具体的做法是把一个大任务分割成小的更容易控制的任务,再继续细分为更小的任务,直到所有的小任务都能很容易实现。\n", + "(2)自顶向下的设计是创建层次化的模块结构的过程,从程序实现和测试的角度看,最好从模块结构图的底层开始实现、运行、测试每一个函数,然后逐步上升,实现上层模块,自底向上直至主程序得到实现。" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "【例4-2-3的程序框架结构】\n", + "def hline(n,ch):\n", + " pass\n", + "def vline(n,ch):\n", + " pass\n", + "def figure(n,ch):\n", + " pass\n", + "def draw():\n", + " pass\n", + "draw() \n" + ] + }, + { + "attachments": { + "image.png": { + "image/png": "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" + } + }, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 小试身手(1)\n", + "(1)修改例4-2-3的程序:如果程序要求当输入一个偶数,图形用*绘制,输入一个奇数,图形用@绘制,应该修改哪个函数?如何修改?\n", + "![image.png](attachment:image.png)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#【例4-2-3】\n", + "def hline(n,ch):\n", + " for i in range(2*n+1):\n", + " print(ch,end=\"\")\n", + " print()\n", + "def vline(n,ch):\n", + " for i in range(n):\n", + " for j in range(n):\n", + " print(\" \",end=\"\")\n", + " print(ch)\n", + "def figure(n,ch):\n", + " hline(n,ch)\n", + " vline(n,ch) \n", + " hline(n,ch)\n", + " \n", + "def draw():\n", + " n=int(input(\"n=\"))\n", + " ch=input(\"ch=\")\n", + " figure(n,ch)\n", + "draw() " + ] + }, + { + "attachments": { + "image.png": { + "image/png": "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" + } + }, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "(2)修改例4-2-3的程序:如果要输出下面图形,应该修改哪个函数?如何修改?\n", + "![image.png](attachment:image.png)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#【例4-2-3】\n", + "def hline(n,ch):\n", + " for i in range(2*n+1):\n", + " print(ch,end=\"\")\n", + " print()\n", + "def vline(n,ch):\n", + " for i in range(n):\n", + " for j in range(n):\n", + " print(\" \",end=\"\")\n", + " print(ch)\n", + "def figure(n,ch):\n", + " hline(n,ch)\n", + " vline(n,ch) \n", + " hline(n,ch)\n", + " \n", + "def draw():\n", + " n=int(input(\"n=\"))\n", + " ch=input(\"ch=\")\n", + " figure(n,ch)\n", + "draw() " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 2.素数问题" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "【4.3.1】 判断一个数n是不是素数" + ] + }, + { + "cell_type": "raw", + "metadata": {}, + "source": [ + "算法:\n", + "1 输入一个数n\n", + "2 i=2\n", + "3 循环当if1,f3=>f2\n", + " 3.3 n 减一\n", + "4.返回 f3" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def fib (n):\n", + " if n<=2:\n", + " return 1\n", + " _____(1)_____\n", + " while n>=3:\n", + " f3=_____(2)_____\n", + " f1,f2=_____(3)_____\n", + " n=_____(4)_____\n", + " return _____(5)_____\n", + "n=int(input(\"n=\"))\n", + "print(fib(n))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## (2) 列表实现" + ] + }, + { + "cell_type": "raw", + "metadata": {}, + "source": [ + "使用列表 FL 存放费波那契数列 \n", + "\n", + "1.如果n=1,2 返回1\n", + "2.FL置初值[1,1]\n", + "3.下标 i 置初值 2 ,指向第三项\n", + "4.循环当 i 小于 n\n", + " 4.1 追加 FL[i-1]+ FL[i22] 到 FL\n", + " 4.2 i=i+1 \n", + "5.返回列表最后一项" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def fib (n):\n", + " if n<=2:\n", + " return 1\n", + " FL= _____(1)_____\n", + " i=2\n", + " while i添加到字典dic\n", + " 3.2 a为b,b为a和b之和\n", + "4.返回字典" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def fib(n):\n", + " a=0\n", + " b=1\n", + " dic=_____(1)_____ #定义字典\n", + " for i in range(n):\n", + " dic[i]=_____(2)_____ #把添加斐波那契数到字典\n", + " a,b=b,a+b\n", + " return _____(3)_____\n", + "\n", + "#调用函数生成斐波那契数列中的前20个斐波那契数\n", + "fibonac= _____(4)_____\n", + "for key in fibonac.keys():\n", + " print(fibonac[key],end=\",\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## (4)递归函数\n", + "\n", + "递归函数是直接或者间接调用自身的函数。 \n", + "注意:可以学完实践13,再做以下两题" + ] + }, + { + "cell_type": "raw", + "metadata": {}, + "source": [ + "如果n等于1或2 则返回1\n", + "否则返回 Fib(n-1)+Fib(n-2)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def Fib(n):\n", + " if n==1 or n==2:\n", + " return _____(1)_____\n", + " _____(2)_____\n", + " return m\n", + "n=int(input(\"n=\"))\n", + "print(Fib(n))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## (5) 优化的递归函数" + ] + }, + { + "cell_type": "raw", + "metadata": {}, + "source": [ + "定义一个全局字典变量d_fib 保存费波那契数列系数\n", + "\n", + "如果 n 存在在字典关键字中\n", + " 则 \n", + " 1.1 返回字典值 \n", + " 否则 \n", + " 1.2 计算递归公式获得第 n 项费波那契数列系数 m\n", + " 1.3 将新的键值对追加到字典\n", + " 1.4 返回 m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "d_fib=_____(1)_____\n", + "def Fib(n):\n", + " if n in d_fib:\n", + " return _____(2)_____\n", + " m= _____(3)_____\n", + " d_fib[n]=_____(4)_____\n", + " return m\n", + "\n", + "n=int(input(\"n=\"))\n", + "print(Fib(n))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.10" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/Lab12.ipynb b/Lab12.ipynb new file mode 100644 index 0000000..bfe5b86 --- /dev/null +++ b/Lab12.ipynb @@ -0,0 +1,988 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# 实践12 再谈python函数\n", + "\n", + "1. 理解函数定义四要素:函数名、参数表、函数体和返回值,本章对每一个部分都进行了更深入的说明,尤其是一些特殊的用法;\n", + "2. 理解 函数定义内外是两个不同的“**作用域**(*scope*)”,区分出全局变量和局部变量,需要充分理解其运作原理;\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "我们已经见过不少函数,也自己写过一些函数。我们已经理解函数的概念来自代数:从**输入参数**出发,**计算**出函数的**返回值**;我们也知道可以用 `def foo():` 来定义函数。其实函数的定义非常复杂,我们不太能够在第一次介绍时就讲清楚,所以之前我们就采取“先引入用起来”的方法,这也是一种知识上的“提前引用”。\n", + "\n", + "本章将围绕函数几个重要的要素深入看看。" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 1. 为函数命名" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "哪怕一个函数内部什么都不干,它也得有个名字,然后名字后面要加上圆括号 `()`,以明示它是个函数,而不是某个变量。" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "def do_nothing():\n", + " pass\n", + "\n", + "do_nothing()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "这就是个“什么也不干”的函数,关键字 `pass` 就是什么也不干的意思。" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "给函数命名(给变量命名也一样)需要遵循的一些规则如下:\n", + "* 首先,名称不能以数字开头,能用在名称开头的只有大小写字母和下划线 `_`;\n", + "* 其次,名称中不能有空格,如果一个名字里有好几个词汇,可以用下划线来分割(`do_nothing`),也可以用所谓 *Camel Case* 风格(*doNothing*),习惯上更推荐使用下划线;\n", + "* 最后,绝对不能与 Python 语言的**关键字**(*keyword*)重复。\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "在程序里给变量、函数命名是个挺重要的事情,影响到程序的可读性,就像小说的语言,最好能有一种流畅清晰、又始终一致的**风格**(*style*)。为了让全世界的 Python 程序员都有相对一致的风格,Python 社区有专门的一套建议规范,放在专门维护 Python 语言特性的社区 [PEP](https://www.python.org/dev/peps/) 上:\n", + "\n", + "* [PEP 8 -- Style Guide for Python Code: Naming Conventions](https://www.python.org/dev/peps/pep-0008/#naming-conventions)\n", + "\n", + "> PEP,是 *Python enhancement proposal* 的缩写,每当有重要的语言特性新需求新想法,就放在这里,经过广大 Python 用户和开发者的讨论完善,在某个版本放进 Python 中。很多 PEP 早已从 *proposal* 毕业变成官方特性,但也还在这里保留着。PEP 8 就是一个古老的 *proposal*,现在已为大多数 Python 用户采纳。" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2. 没有、一个和多个参数" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "函数可以没有参数,也可以有一个或者多个参数。\n", + "\n", + "没有参数就意味着,这个函数执行不依赖于输入,比如我们定义一个函数来在程序结束时打印一句退出提示:" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Program exits. Bye.\n" + ] + } + ], + "source": [ + "def exit_info():\n", + " print('Program exits. Bye.')\n", + " \n", + "exit_info()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "注意即使没有参数,无论定义还是调用时,函数名后面的括号都是不可省略的,这是函数身份的标志。" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "函数也可以有多个参数,调用时输入参数的值是严格按照参数的顺序去匹配的。比如我们写一个函数输出某年到某年之间的所有闰年:" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2000\n", + "2004\n", + "2008\n", + "2012\n", + "2016\n" + ] + } + ], + "source": [ + "def leap_years(begin, end):\n", + " year = begin\n", + " while year < end:\n", + " if (year % 4 == 0 and year % 100 != 0) or year % 400 == 0:\n", + " print(year)\n", + " year += 1\n", + " \n", + "leap_years(2000, 2020)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "当我们调用 `leap_years(2000, 2020)` 时,输入两个参数值 2000 和 2020,按照顺序匹配函数定义 `leap_years(begin, end)`,于是 `begin = 2000` `end = 2020`。所以参数的顺序是不能搞错的,有些函数参数很多,要是开发过程中还调整过顺序的话,那简直就是灾难,所以一般情况下还是保持函数参数不要乱动为好。\n", + "\n", + "顺便说一句,判断闰年的算法虽然不难,但要写的简洁也不容易。建议你可以先自己思考和实现一遍,然后尝试搞清楚为啥上面代码里的那行 `if` 是对的。实际上闰年的判断有很多正确的写法,你应该尝试写出自己的版本并确认它的正确性。" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 3. 没有、一个和多个返回值" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "和参数一样,Python 的函数可以没有返回值,也可以有一个或者多个返回值。\n", + "\n", + "上面的 `exit_info` 和 `leap_year` 也是没有返回值的例子,它们的效果都通过 `print` 函数来体现。实际上没有返回语句的函数,等价于在其最后有一句 `return None`,表示函数返回了一个空值 `None`,`None` 在 Python 中是一个合法的值,表示什么都没有,它在逻辑上等价于 `False`:" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "False" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "bool(None)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "所以即使没有返回值的函数,也可以用在 `if` 后面做逻辑表达式,不过我们并不推荐这么做,因为可读性很差。" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "大部分情况下函数是有返回值的,因为绝大部分情况下函数的作用都是做“数据处理”,从输入出发得到输出。\n", + "\n", + "一般情况下函数都只有一个返回值,我们已经见过不少例子;但 Python 也允许多返回值,比如我们想用一个函数来计算两个整数相除的商和余数,可以这么写:" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "8 2\n" + ] + } + ], + "source": [ + "def idiv(a, b):\n", + " quotient = a // b\n", + " remainder = a % b\n", + " return quotient, remainder\n", + "\n", + "q, r = idiv(50, 6)\n", + "print(q, r)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "和多参数的情况类似,多返回值的情况下,赋值也是按照顺序匹配的,上面的代码中赋值语句左边的 `q` 匹配到第一个返回值,`r` 匹配第二个。" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 4. 函数内与函数外:变量的作用域" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "下面的代码经常会把人搞晕:" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2\n", + "1\n" + ] + } + ], + "source": [ + "def increase_one(n):\n", + " n += 1\n", + " return n\n", + "\n", + "n = 1\n", + "print(increase_one(n))\n", + "print(n)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "请你思考一下,为什么这段代码里的两个 `print` 函数输出分别是 2 和 1。\n", + "\n", + "这个问题就涉及到变量的**作用域**(*scope*)问题,也就是说在不同地方出现的同名变量和函数,可能是完全不同的两个东西:\n", + "* 函数定义体中的变量的作用域是该函数内,程序的其他部分不知道其存在,这种变量叫**局部变量**(*local variable*);函数的输入参数也是局部变量,也只在函数定义体中有效;\n", + "* 不在任何函数、类定义体中的变量的作用域是全局的,在任何地方都可以访问,这种变量称为**全局变量**(*global variable*);\n", + "* 如果局部变量和全局变量同名,函数定义体内会优先局部变量,不会把它当做全局变量。\n", + "\n", + "这样我们就能理解上面代码输出的 2 和 1 了:\n", + "* 第一个 `print()` 打印的是函数调用 `increase_one(n)` 的返回值,这个语句不在任何函数定义体中,所以它里面用到的变量都是全局变量:\n", + " * 在调用 `increase_one()` 时参数 `n`,按照作用域原理,是全局变量 `n` 当时的值,也就是 1;\n", + " * 在 `increase_one()` 函数定义内,参数 `n` 是输入参数即局部变量,带着传进来的值 1,经过加一之后返回,返回值是 2;\n", + " * `print` 打印这个返回值,输出 2;\n", + " * 这个过程中处理的都是局部变量,完全不影响全局变量 `n` 的值;\n", + "* 第二个 `print()` 打印的是全局变量 `n` 的值,输出出 1。" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "以上的文字,可能需要反复阅读若干遍;几遍下来,消除了疑惑,以后就彻底没问题了;若是这个疑惑并未消除,或者关键点并未消化,以后则会反复被这个疑惑所坑害,浪费无数时间。\n", + "\n", + "顺便说一句,上面这个例子用来说明作用域的概念很有用,但是平时写程序最好别这么写,减少重名的变量可以提升代码的清晰度和可读性。" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "与此相关的,我们在介绍列表等数据容器时,会为上面的规则作出重要的补充,这里先留一个伏笔。" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 5. 带缺省值的参数" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "我们其实已经见过带缺省值的参数(*argument with default value*),这里我们更细致的看看这个特性。\n", + "\n", + "在函数定义中可以在某个参数后面用等号 `=` 给它一个缺省值,调用时可以省略传入这个参数的值,直接采用缺省值;当然也可以在调用时传入这个参数的值来覆盖掉缺省值。这种特性相当于给了这个函数两个版本,一个带某个参数,一个不带,不带的版本就当该参数是某个缺省值。看看下面的例子:" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [], + "source": [ + "def greeting(name, msg='Hi'):\n", + " print(f'{msg}, {name}!')" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Hi, Neo!\n" + ] + } + ], + "source": [ + "greeting('Neo')" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Good morning, Neo!\n" + ] + } + ], + "source": [ + "greeting('Neo', 'Good morning')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "一个函数可以有多个带缺省值的参数,但有一个限制:所有这些带缺省值的参数只能堆在参数表的最后,也就是说你定义的参数表里,出现一个带缺省值的参数,则它后面的都必须带缺省值。如果把上面的 `greeting()` 函数的两个参数调换一下,会扔出一个 `SyntaxError: non-default argument follows default argument` 的异常。" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 6. 指定参数名来调用函数" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "我们前面说过,调用函数时传入的参数值会严格按照顺序去匹配参数变量,第一个输入值赋给第一个参数变量,第二个值赋给第二个参数变量,依此类推。因为有了上面说的带缺省值参数,这个规则出现了变通的可能。\n", + "\n", + "如果一个函数有多个带缺省值的参数,我们想忽略掉某几个参数(就用其缺省值),但指定后面某一个参数的值(覆盖缺省值),例如下面这个函数:" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [], + "source": [ + "def greeting(name, msg='Hi', punc='!'):\n", + " print(f'{msg}, {name}{punc}')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "在这个版本的 `greeting()` 函数中,包含一个普通参数 `name` 和两个带缺省值的参数 `msg` `punc`,如果我们想跳过 `msg` 只传入 `name`(这个是必须的,因为没有缺省值)和 `punc` 的值,那么就可用下面的语法:" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Hi, Neo.\n" + ] + } + ], + "source": [ + "greeting('Neo', punc='.')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "这里第一个值按照顺序位置匹配到参数变量 `name`,这叫 *positional argument*(即“按照位置顺序匹配的参数”),而按照位置下一个是 `msg`,是我们想跳过的,所以要注明参数变量名,说明下一个传入的值 `'.'` 是给 `punc` 参数变量的,这叫 *keyword argument*(即“按照参数名匹配的参数”)。\n", + "\n", + "由于所有带缺省值的参数都在普通参数的后面,所以我们只要记住:\n", + "* 调用函数时先传入所有不带缺省值的参数的值,严格按照函数定义的位置顺序(*positional*);\n", + "* 然后想指定哪些带缺省值参数的值,就用 `变量名=值` 这样的格式在后面列出(*keyword*),未列出的就还用缺省值了。\n", + "\n", + "在后半部分,顺序就无所谓了,可以和定义时不一样,反正是用名字指定的(*keyword*),比如我们完全可以这么干:" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Good nite, Neo.\n" + ] + } + ], + "source": [ + "greeting('Neo', punc='.', msg='Good nite')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 7. 变长参数" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "到目前为止,Python 的函数定义还是很简单清晰的,无论参数还是返回值,都没什么难懂的。下面开始就要进入比较混沌的领域了。\n", + "\n", + "所谓变长参数就是函数定义时名字前面带个星号 `*` 的参数变量,这表示这个变量其实是一组值,多少个都可以。我们先来看个简单的例子:" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [], + "source": [ + "def say_hi(*names):\n", + " for name in names:\n", + " print('Hi,', name)" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Hi, Neo\n" + ] + } + ], + "source": [ + "say_hi('Neo')" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Hi, Neo\n", + "Hi, Trinity\n" + ] + } + ], + "source": [ + "say_hi('Neo', 'Trinity')" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Hi, Neo\n", + "Hi, Trinity\n", + "Hi, Morpheus\n" + ] + } + ], + "source": [ + "say_hi('Neo', 'Trinity', 'Morpheus')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "在这个例子里,`*names` 是一个变长参数(*arbitrary argument*),调用时可以传入一个或者多个值,函数会把这些值看做一个列表,赋给局部变量 `names`——后面我们会知道,其实不是**列表**(*list*),而是一个**元组**(*tuple*)——然后我们在函数体中可以用 `for...in` 来对这个 `names` 做循环。\n", + "\n", + "> 有些中文书籍把 *arbitrary arguments* 翻译成“可变参数”或者“任意参数”。事实上,在这样的地方,无论怎样的中文翻译都是很难准确表达原意的。这还算好的,甚至还见过翻译成“武断的参数”的——这样的翻译肯定会使读者产生说不明道不白的疑惑。\n", + ">\n", + "> 所以,**入门之后就尽量只用英文**是个好策略。虽然刚开始有点吃力,但后面会很省心,很长寿——是呀,少浪费时间、少浪费生命,其实就相当于更长寿了呀!" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "在使用 *arbitrary argument* 的场合,有几点需要注意:\n", + "* 参数变量名最好用复数单词,一看就知道是一组数据;这个变量在函数里通常都会被 `for...in` 循环处理,用复数名词在写类似 `for name in names` 的循环语句时会很舒服、很地道(*idiomatic*),是的,写程序和学外语一样,不写则已,写就要尽量写得“地道”;\n", + "* 这种参数变量只能有一个,因为从它开始后面的输入值都会被当做它的一部分,多了就不知道怎么分了,显然,如果有这种参数,必须放在参数表的最后。\n", + "\n", + "上面的第二点,有一个不太常见的例外,那就是一个函数既有 *arbitrary arguments* 又有 *arguments with default values* 的情况,那么可以有两个 *arbitrary arguments*,其中第二个必须带缺省值,然后参数表排列成这样:\n", + "\n", + "`def monstrosity(*normal arguments*, *normal arbitrary argument*, *arguments with defaults*, *arbitrary argument with default*)`\n", + "\n", + "这样是完全符合语法要求的,调用时传入参数值还是按照前面讲的规则,先按照位置顺序匹配前两部分,多出来的都归 *normal arbitrary argument*;然后按照参数变量名指定对应值,没指定的都用缺省值。不过这实在是太麻烦了,不知道什么情况下才必须用这么可怕的函数,还是祈祷我们不会碰到这样的场景吧!\n", + "\n", + "当然,只有上面列出的前三个部分的情况还是有的,比如下面的例子:" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [], + "source": [ + "def say_hi(*names, msg='Hi', punc='!'):\n", + " for name in names:\n", + " print(f'{msg}, {name}{punc}')" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Hi, Neo.\n", + "Hi, Trinity.\n" + ] + } + ], + "source": [ + "say_hi('Neo', 'Trinity', punc='.')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 小试身手(1)\n", + "阅读可变参数的vfunc函数,仿写milti函数实现返回所有参数的乘积。" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "def vfunc(*b):\n", + " a=0\n", + " for n in b:\n", + " a+=n\n", + " return a\n" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "15" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "vfunc(1,2,3,4,5)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 函数别名" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "在 Python 中,所有函数也是对象,证据就是它们都有对象 id。Python 会为创建的每一个对象(不管基本数据类型,还是某个 *class* 的实例)指定一个唯一的 id,可以用内置函数 `id()` 来查看,比如:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "n = 42\n", + "id(n)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "函数也有这个 id,比如:" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "def _is_leap(year):\n", + " return (year % 4 == 0 and year % 100 != 0) or year % 400 == 0" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "2989669354808" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "id(_is_leap)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "既然函数有 id,是个对象,那是什么类型的对象呢?可以用内置函数 `type` 来看:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "type(_is_leap)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "所以函数是个 `function` 类型的对象。\n", + "\n", + "既然是个对象,我们就可以用赋值语句来创建函数的**别名**(*alias*):" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "is_leap = _is_leap" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "id(is_leap)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "可以看到,这两个函数的 id 完全一样,是同一个对象的两个名字而已。我们可以用这两个名字来调用这个函数,完全没区别:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "_is_leap(2018)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "is_leap(2018)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "那么,我们为什么需要给函数取别名呢?\n", + "\n", + "很多时候是为了提供更好的代码可读性,比如在特定上下文让某个函数的作用更显而易见,比如以前的例子里,我们曾经在 `Cat` 类里给父类 `Animal` 的 `voice()` 方法定义别名叫 `meow()`。\n", + "\n", + "还有一种情况是一个函数需要在运行时动态指向不同的实现版本。这里只简单描述一个典型场景:假定我们要渲染一段视频,如果系统里有兼容的显卡(GPU),就调用显卡来渲染,会更快更省电,如果没有则用 CPU 来渲染,会慢一点和更耗电一点,于是我们把用 GPU 渲染的算法写成函数 `_render_by_gpu()`,用 CPU 渲染的算法写成函数 `_render_by_cpu()`,而检测是否存在可用 GPU 的算法写成函数 `is_gpu_available()`,然后可以用下面的方法来定义一个函数 `render`:\n", + "\n", + "```python\n", + "if is_gpu_available():\n", + " render = _render_by_gpu\n", + "else:\n", + " render = _render_by_cpu\n", + "```\n", + "\n", + "这样 `render()` 就成为一个当前系统中最优化的渲染函数,在程序的其他地方就不用管细节,直接用这个函数就好。这就是动态函数别名的价值。\n", + "\n", + "顺便说一句,在任何一个工程里,为函数或者变量取名都是**很简单却不容易**的事情——因为可能会重名(虽然已经尽量用变量的作用域隔离了),可能会因取名含混而令后来者费解,所以,仅仅为了少敲几下键盘而给一个函数取个更短的别名,实际上并不是好主意,更不是好习惯。尤其现在的编辑器都支持自动补全和多光标编辑的功能,变量名长点不是什么大问题。" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 匿名函数" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "有的函数需要两个甚至更多名字,有的函数却一个也不要,人生就是这么丰富多彩啊!\n", + "\n", + "所谓匿名函数,就是有时候我们需要一个函数,但就在一个地方,用完就扔,再也不会用了,Python 对这种情况提供了一个方便的语法,不需要 `def` 那套严肃完整的语法,一行就可以写完一个函数,这个语法使用关键字 `lambda`。`lambda` 是希腊字母 `λ` 的英语音译,在计算机领域是个来头不小的词儿,代表了一系列高深的理论,[和阿伦佐·丘奇(Alonzo Church)的理论有关](https://en.wikipedia.org/wiki/Lambda_calculus),有兴趣的话可以自行研究。\n", + "\n", + "不过目前我们不需要管那么多,只要了解怎么快速创建“用过即扔”的小函数就好了。" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def add(x, y):\n", + " return x + y\n", + "add(3, 5)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "我们可以用 lambda 来改写:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "add = lambda x, y: x + y\n", + "add(3, 5)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "甚至更简单一点,名字也不要了:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "(lambda x, y: x + y)(3, 5)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "最后这种形式,就是典型的匿名函数了。简单地说,`lambda` 可以生成一个函数对象,出现在所有需要一个函数的地方,可以将其赋给一个变量(如上面的 `add`),这个变量就称为函数变量(别名),可以当函数用;也可以直接把 `lambda` 语句用括号括起来当一个函数用(上面后一种形式)。\n", + "\n", + "在 Python 官方文档中,`lambda` 语句的语法定义是这样的:\n", + "\n", + "`lambda_expr ::= \"lambda\" [parameter_list] \":\" expression`\n", + "\n", + "这个语法定义采用的是 [巴克斯范式(BNF)](https://en.wikipedia.org/wiki/Backus%E2%80%93Naur_form)标注,现在不明白没关系(虽然对照上面的例子也能猜出个大概吧),以后我们会专门介绍。\n", + "\n", + "其实也很简单,就是这个样子:\n", + "\n", + "```python\n", + "lambda x, y: x + y\n", + "```\n", + "\n", + "先写上 `lambda` 关键字,其后分为两个部分,`:` 之前是参数表,之后是表达式,这个表达式的值,就是这个函数的返回值。**注意**:`lambda` 语句中,`:` 之后有且只能有一个表达式,所以它搞不出很复杂的函数,比较适合一句话的函数。\n", + "\n", + "而这个函数呢,没有名字,所以被称为 “匿名函数”。\n", + "\n", + "`add = lambda x, y: x + y`\n", + "\n", + "就相当于是给一个没有名字的函数取了个名字。" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 小试身手(2)" + ] + }, + { + "cell_type": "raw", + "metadata": {}, + "source": [ + "1.判断奇数 \n", + "判断奇数的函数lambda函数的定义和使用 \n", + "(1)使用匿名函数编写一个函数isOdd,能够判断一个整数是否是奇数,返回True或False。\n", + "isodd = lambda x: x%2 == 1\n", + "(2)请写出输入一个数x,调用isOdd函数判断x是否是奇数的程序段。 \n", + "(3)请写出求50-100之间所有奇数的和的程序段,(使用isOdd实现奇数判断)。 \n", + "(4)请写出求50-100之间所有偶数的和的程序段(使用isOdd实现偶数判断)。\n" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [], + "source": [ + "isodd = lambda x: x%2 == 1" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "2.构造整数\n", + "问题描述\n", + "求由任意个整数上的个位数构造的新整数并输出。\n", + "具体要求\n", + "(1)编写lambda函数getLastBit,该函数返回正整数number的个位数,例如正整数1234,则返回4。\n", + "(2)编写可变参数的函数makeNumber,求任意个整数的个位数构成的一个新整数。\n", + "(3)输出(45、81、673、938)4个数的个位数构成的新整数,得到的新的整数为:5138。请填空完整程序。\n", + "\n", + "新整数是5138" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#定义lambda函数getLastBit返回一个数的个位数\n", + "getLastBit= \n", + "\n", + "#定义一个可变参数的函数makeNumber,求任意个整数的个位数构成的一个新整数\n", + "def makeNumber(a,*b):\n", + " s=getLastBit(a)\n", + " \n", + "\n", + "\n", + " return s\n", + "\n", + "#输出(45、81、673、938)4个数的个位数构成的新整数。\n", + "print(f\"新整数是{makeNumber(45,81,673,938)}\")\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.10" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/Lab13.ipynb b/Lab13.ipynb new file mode 100644 index 0000000..26a33f6 --- /dev/null +++ b/Lab13.ipynb @@ -0,0 +1,413 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# 实践13 递归函数\n", + "1.理解递归 \n", + "2.掌握递归函数的定义和调用\n", + "3.理解递归函数的调用过程" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 1.递归" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "递归是个很有趣也很有用的概念。所谓“**递归**(*recursion*,*recursive*)”,就是“用自己定义自己”,或者“自己包含自己”。举个例子,大家都听过的这个故事就是递归的经典例子:\n", + "\n", + "```\n", + "从前有座山,山里有座庙,庙里有个老和尚,正在给小和尚讲故事呢!故事是这样的:从前有座山,山里有座庙,庙里有个老和尚,正在给小和尚讲故事呢!故事是这样的:从前有座山,……\n", + "```\n", + "\n", + "如果我们把这个故事叫做 A,那么 A 的定义可以写作这样:\n", + "\n", + "```\n", + "A ::= 从前有座山,山里有座庙,庙里有个老和尚,正在给小和尚讲故事呢!故事是这样的:A\n", + "```\n", + "\n", + "上面这个定义里的 `::=` 的意思是“定义为”,这种语法叫 [巴科斯范式(BNF)](https://en.wikipedia.org/wiki/Backus%E2%80%93Naur_form)。这个定义里最有意思的地方是,在 A 的定义中用到了 A 本身,如果我们把 A 的定义代入 `::=` 右边出现的 A,就会出现无限循环下去的情况,这恰恰是原来那个故事的 point 所在。" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "如果把这个故事写成 Python 代码,大致是这样子的\n", + "\n", + "```python\n", + "def a_monk_telling_story():\n", + " print('从前有座山,山里有座庙,庙里有个老和尚,正在给小和尚讲故事呢!故事是这样的:')\n", + " return a_monk_telling_story()\n", + "```\n", + "\n", + "这个简短的程序体现了递归的本质:一个函数的定义中调用了自己。不过我们可不能真写这样的程序,因为它会无限的自我调用下去,形成“无限循环”,或者更难听的词儿“死循环”——循环到死。" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 2. 递归的基本概念" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "递归在编程中很有用,要了解这一点,我们可以来了解递归的来源:又是数学。人们很早就意识到,数学上有一类东西,很不好写出一个公式来计算,但用自己来定义自己反而会很清晰和严谨,比如大名鼎鼎的斐波那契(*Fibonacci*)数列,这个数列不仅有很高的理论价值,而且有很多数学和其他学科里的直接应用,它的定义是:" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\\begin{equation*}\n", + " f(n) = \\begin{cases}\n", + " 0 & n = 0\\\\\n", + " 1 & n = 1\\\\\n", + " f(n-1) + f(n-2) & \\text{otherwise}\n", + " \\end{cases}\n", + "\\end{equation*}" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "也就是说,开头两项是 0 和 1,之后每一项都是前两项之和,这个定义来自数学家 Leonardo Fibonacci 对兔子生长问题的研究:\n", + "* 第一个月初有一对刚诞生的兔子;\n", + "* 第二个月之后(第三个月初)它们可以生育;\n", + "* 每月每对可生育的兔子会诞生下一对新兔子;\n", + "* 兔子永不死去。\n", + "\n", + "在这一模型下,每个月兔子的数量就可以简单直观地用上面的递归表达式来表示。而要写出斐波那契(Fibonacci)数列的通项公式(即通过 n 的有限次运算求出第 n 项的值)就没那么容易了,当然这个公式目前不算什么了,长这样:" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\\begin{equation*}\n", + " f(n) = \\frac{1}{\\sqrt{5}}((\\frac{1+\\sqrt{5}}{2})^{n} - (\\frac{1-\\sqrt{5}}{2})^{n})\n", + "\\end{equation*}" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "所以可以看出,递归表达式和通项表达式很不一样,有时候递归表达式代表了问题的本质,从递归表达式出发就可以一个一个计算出值来,而通项表达式更方便快速计算出特定某一项来,却完全看不出和最初的问题有什么关联。" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "另一个经典的递归例子是阶乘的定义,n 的阶乘 $n!$ 就是从 1 开始一直乘到 n,递归定义很简单:" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\\begin{equation*}\n", + "n! = (n-1)! \\times n\n", + "\\end{equation*}" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "可要写出它的通项,怎么写呢?当然我们可以写 `n! = 1x2x3x...xn`,但是 `...` 并不是在数学上严谨的一个东西啊。" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "为了用 Python 计算阶乘的值,可以有两种方法,循环,和递归。先来看循环的方法:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "result = 1\n", + "for i in range(5):\n", + " result = result * (i+1)\n", + "print(result)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "就是把 1~n 的整数都乘起来,下面看看递归的方法:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def f(n):\n", + " if n == 1:\n", + " return 1\n", + " else:\n", + " return n * f(n-1)\n", + " \n", + "f(5)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "和前面的版本结果一样。这个实现基本就是阶乘数学定义的翻译,很容易明白,但我们需要格外关注的是在函数里调用自己这件事。我们可以一层一层的分析一下在函数调用 `f(5)` 之后到底发生了什么。" + ] + }, + { + "attachments": { + "image.png": { + "image/png": "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8pJLLhnHOaxMOh+vKjjnox97cxVFEZwRgg4++OC4IBS+BotNUq+Txu+TTz45Lir34IMPxkkoROltt902Li43YMCAsMACC4Rf/OIXcVI84b3mmmvGhW5vvPHG5KVC/FZwLkQ317zIIgnOxx9/fMAGYDfmm2++wOQUjSyqESNGRF8DYYRGnfB99tkn2gU+M88884Qdd9wx3HrrrV1+BXaFReXwT5IoxvjhHP+j4Jzjzq3z0ooiODOphK8w/fTTR5ux3HLLdU1KE+yC5jH55JPHCanSCGeinvHHll122XDppZd2UcV3YR9oHdiRIjUF5yL1ttfaEQJFEJwxtLfffnsYPHhwGDhwYBg+fHgUipLIZGbzVlpppfiD2EzEwNZbbx0mmWSSsO6668afddZZJ6yxxhpROEJEIlLxoosuCosuumhYbbXVKopNHenQNhxUwbkNkFN+iKIIzgge2IaZZpopHHDAAWHkyJFd4hERjNgEnDaiEssbi0atuuqqcZC43nrrdQnORCsuvfTSYciQIYWJPFJwLr87ivf/IgjORBHdfPPNUTSed955w2GHHRa495PsByIOl19++Wg3mLBisIcPMdVUU8XXtthiizBo0KA4eMSuELlEYwKcSfL111+/UDeOgnOhurvixRZFcCbYhSCX2WabLU5YEWmI0Ewjs4rglxVWWCEGxIwZMyasuOKKUUzCTiCw8VnEJewO2ZcIzOyDCS8+V5SSPArOFR+jQr1YBMEZsfn666+PwSsEtRx55JHxuU8imZlkwjYw9kjsCDcB71911VVhlllmiT8EvpS2k046KU52bbXVVqUv5/5vBefcd7EX2GkCeRacS2f0Mar9+/cPm2yySZwBTNJViVRmUMh7iGiI08zs4cwRGfDoo4/GH1JV/va3v8U02X/84x+x2yjDQURB3759YwpKMqjsdJ+2+vgKzq0mnP7951lwLrUbDNwQgBiwkQmRPOP8JvKZZ5+MB2qsljbsClHNTFpNOumk0eljkopGaizi9cQTTxwdxiKkySs4l94dxfw7z4Jzqc3ANmIXdthhhyjyJL4GAjMRiQhKTFwRZbTpppuG6aabLgpGlPti4orBIKI0tuOYY46JNgdfY7PNNosTX/fee2/X5FXe7yQF57z3cPfXl2fBudRukC0166yzhrXXXjuW7Up8DYTi4447LkYx/v73vw9ELpIl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U8F5xIgRYb311gsLLrhgmHfeecNUU00VZpttttQLzhdccEE85/nnnz8ssMACUXBeYYUVjHCu94ZxOwlIQAISkIAEJCABCUhAAhKQgAQkIAEJSEAC1Qj0VHBmob0rr7wyXHrppeH8888PCy+8cBg4cGDqazg/9thj8Xwp/YH4POuss8ZoZ0tqVLtDfF0CEpCABCQgAQlIQAISkIAEJCABCUhAAhKQQJ0Eeio4l+6eOs7rrrtumHvuucOFF15Y+lbVv1mw77///W+glnK1H97/6quvwrfffhu+/PLLqtsln//8888D+623se/BgweHxRZbzAjneqG5nQQkIAEJSEACEpCABCQgAQlIQAISkIAEJCCBagSaITh/8sknYe21125IcL7hhhvCdtttF4YNG1b1Z4cddogLEj711FPh7LPPDnvssUfYddddK26/8847hwMPPDBce+214X//+1+1yx3ndQRtxGYF53Gw+B8JSEACEpCABCQgAQlIQAISkIAEJCABCUhAAj0j0AzB+eOPP25YcCYSeokllggrrbRS1Z8hQ4aE0047LTz00ENh+PDhYdVVVw0s8FfpM8stt1zYeOONY5mMeqOcP/30UwXnnt02fkoCEpCABCQgAQlIQAISkIAEJCABCUhAAhKQwPgEOiU4P/vsszF6mTrQ1X4uu+yyQK3of/3rX+Evf/lLuOqqq8Lo0aMrbj9q1KhA1PTTTz8dS3CMf6Xjv6LgPD4TX5GABCQgAQlIQAISkIAEJCABCUhAAhKQgAQk0GMCnRKce3zCTfyggnMTYborCUhAAhKQgAQkIAEJSEACEpCABCQgAQlIQAKdEpxfeOGFGLFMVHK1n2uuuSZQv/m9994Ljz76aLjxxhvD9ddfX3H76667Ltx6663h+eefN8LZ21oCEpCABCQgAQlIQAISkIAEJCABCUhAAhKQQCcIdEpwPuqoo0KfPn3ChBNOWPWH9/fcc89w8803hw033DBMNtlkVT/DtgMGDAiHHnpo+PLLL+tCaYRzXZjcSAISkIAEJCABCUhAAhKQgAQkIAEJSEACEpBAfQQ6JTg/+eSTYcSIEeHSSy+t+sPCgo888kh45513wj333BMuv/zycMkll1TcfuTIkeHqq6+OEdHffvttXRev4FwXJjeSgAQkIAEJSEACEpCABCQgAQlIQAISkIAEJFAfgWYIzh99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GQYPHhz+9re/peEUPYf/T0DB2VtBAhKQgAQkIAEJSEACEpCABCQgAQlIQAISSDWBzz//PBx11FGxfMYiiywSZp555nDooYfG8hpvvPFGqs+9aCen4Fy0Hvd6JSABCUhAAhKQgAQkIAEJSEACEpCABCSQMQKUzHj88cfDJptsEiabbLIw0UQTxTrOd9xxR/jiiy8ydjX5Pl0F53z3r1cnAQlIQAISkIAEJCABCUhAAhKQgAQkIIHcENhggw1Cnz594s8CCywQPvzww9xcW14uRME5Lz3pdUhAAhKQgAQkIAEJSEACEpCABCQgAQlIIOcETjnllDD77LOHaaaZJuy7777hyy+/zPkVZ+/yFJyz12eesQQkIAEJSEACEpCABCQgAQlIQAISkIAECkngiSeeCMsvv3yYaaaZAuU0vv3220JySPNFKzinuXc8NwlIQAISkIAEJCCY0h1aAAAgAElEQVQBCUhAAhKQgAQkIAEJSKCLAPWaL7nkkkCk88cffxy+//77rvf8Ix0EFJzT0Q+eRQsIaHBaALVgu/QeKliHh6CjUrwu94ol0CsCfk/0Cp8flkAhCWg3CtntXrQEekxAm1EdHVHNLhRYnU+n32lYcH755ZcDP0899VR4+umnU/uTnN9LL71kaH2n77IOHv+DDz5I7T2a5uenqOeW2I3nn38+fP311x28cz10Jwl88skn4ZlnntF2pPg7Pi02KrEZ+EXfffddJ29bj91BAu+//772QntR9z2Q2I0XX3wxfPPNNx28cz10Jwl89NFH+hrajbrsBjaDn1dffbWTt6zH7jCB9957L94vyXdIWnzhTp/Hs88+G5577rm6nqVOn2s7j5/cJ53WQxsWnPv169e1EmSyImSaf1NAHNHRVkwCp59+eqbu1zQ/S0U6twkmmCC88sorxXxovOowatQo7cb/X/G5SM99b66V2nGfffaZT09BCfzqV7/SZmgzGr4HJptssvDOO+8U9Knxss8///yG75nefE/52T6Z5z3XXHMZSFdg07H//vtn/h7WDrXfDqHffvjhhx17cnokOI8YMSL885//jDMJzCak8eett94KfJH/6Ec/CkSe2IpJgEFg//79Y1T+Cy+8kMp7NY3PT1HP6Y033gjXXntt/DLnfrEVk8Af//jHgBDALDSzwkV9Hrzu7v0bfCHqxk0++eQKzsU0F/Gqf/nLX4aBAweG119/PZAh47PT/bNTZEZvvvlmGDlyZPQ1sCG2YhL47W9/G/r27RvwN4l2L/Iz4bXXtplvv/12OOqoo8J0002n4FxMcxGveqeddgoLLbRQYLzqM1P7mZHPc1GvPfvss8NEE03U0QDcHgnODz74YCYe9b/85S8RsIJzJrqrJSd5zDHHhLnnnrsl+3an+SRAuhqzrwrO+ezfeq7qD3/4Q3Tq69nWbSRw4403himmmELBucC3wn777RcGDx5cYAJeeqMEHn/88UA2lYJzo+Tysz2TlbPPPnt+LsgraSmBSy+9VMG5pYTTv/Mdd9wxrLTSSuk/Uc8wNQTuuuuuMMkkk2RPcObEs9Buv/12BecsdFQLz5EIZ9KPbBKolwBRrQrO9dLK53ZEOJN+ZG3NfPZvs6/qT3/6U5hyyikVnJsNNkP7I8J5kUUWydAZe6qdJkBQjIJzp3uhs8cnwnnWWWft7El49MwQIBhi+umnN8I5Mz3W/BP9+c9/HpZffvnm79g95pbAn//8ZwXnVvaugnMr6WZj3wrO2einNJ2lgnOaeqMz56Lg3BnuWT2qgnNWe655563g3DyWRdmTgnNRerr6dSo4V2fjO+MTUHAen0nRXlFwLlqP9/56FZx7z7DmHhSca+IpxJsKzoXo5qZepIJzU3FmcmcKzpnsto6dtIJzx9Cn5sAKzqnpisyciIJzZrqqZSeq4NwytLncsYJzLru1oYtScG4IlxuHEBScW3wbKDi3GHAGdq/gnIFOStkpKjinrEM6cDoKzh2AnuFDKjhnuPOadOoKzk0CWaDdKDgXqLOrXKqCcxUwvlyRgIJzRSyFelHBuVDd3ZSLVXBuCsbqO1Fwrs6mKO8oOBelp5t3nQrOzWOZ1T0pOGe15zpz3grOneGepqMqOKepN7JxLgrO2einVp6lgnMr6eZv3wrO+evTRq9IwblRYm6v4Nzie0DBucWAM7B7BecMdFLKTlHBOWUd0oHTUXDuAPQMH1LBOcOd16RTV3BuEsgC7UbBuUCdXeVSFZyrgPHligQUnCtiKdSLCs6F6u6mXKyCc1MwVt+JgnN1NkV5R8G5KD3dvOtUcG4ey6zuScE5qz3XmfNWcO4M9zQdVcE5Tb2RjXNRcM5GP7XyLBWcW0k3f/tWcM5fnzZ6RQrOjRJzewXnFt8DCs4tBpyB3Ss4Z6CTUnaKCs4p65AOnI6CcwegZ/iQCs4Z7rwmnbqCc5NAFmg3Cs4F6uwql6rgXAWML1ckoOBcEUuhXlRwLlR3N+ViFZybgrH6ThScq7MpyjsKzkXp6eZdp4Jz81hmdU8Kzlntuc6ct4JzZ7in6agKzmnqjWyci4JzNvqplWep4NxKuvnbt4Jz/vq00StScG6UmNsrOLf4HlBwbjHgDOxewTkDnZSyU1RwTlmHdOB0FJw7AD3Dh1RwznDnNenUFZybBLJAu1FwLlBnV7lUBecqYHy5IgEF54pYCvWignOhurspF6vg3BSM1Xei4FydTVHeUXBuT09///337TlQG46i4NwGyCk/hIJz+joozTZGwTl990u7z0jBud3Euz9emm0GZ6/g3H0f5n0LBef09XC9dqPe7Zp5hQrOzaSZzX0pOGez3zp51grOLaav4NxiwBnYfdoF5//973/hyy+/DN9++21qaX7zzTfhvffeC//617/CO++8M94P51/a2PbDDz8MfK68se27774b3nrrrfDGG2+E//u//wuffvppqMdx++STT8Kbb74Z+P3dd9+V77pp/1dwbhrKzO4oi4Izz8RXX30Vvv7667qep7R0DufLc/2f//wnYA/L27///e9oc8pf5/9cL5/Dnvzzn/8M77//fvjiiy8qbdrS1xScW4o3EzvPouCM38F3Ms9gmhvnmTzn+A3Js17Jx+A68CvYvrxhXz744IPw9ttvR/+D/fD/Tl2/gnN5DxXv/1kUnEvtRj2+e6d6lXP76KOPup53/AT8iWrPO2MTfmo1xh+Mg9hvJ5qCcyeop+uYeRWcE7uCX5+Vhn6BNoIfkeam4Nzi3lFwbjHgDOw+zYIzxhVxE0PAAIn/p7HhpP30pz8Na6+9dlhzzTXDWmut1fWzxhprxCid5Lxx8LbddttwzDHHhJdffjl5Of7GybvpppvCxhtvHBZccMEwaNCgsNJKK4XTTz+9WyePL6CTTz45fuacc86JIvU4O2/ifxScmwgzo7vKouDMRM9tt90WHnroofD5559ngjw2j/Odc845w7777huef/758c57xx13DNiZ8oajd+edd4bdd989LLLIImHw4MFh1113Dddee23bRWcF5/LeKd7/syg4v/7669FmPPbYYxUniNPQi4jKL774Yhg2bFhYdNFFw8CBA+Ozvttuu4Unn3yy4iTV8ssvH37xi1+M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gSAQBIJAEAgCQSAIBIEgEASCQBAIAkEghHOegSAQBIJAEAgCQSAIBIEgEASCQBAIAkEgCASBIBAEgkAQmASBEM6TwJhOgkAQCAJBIAgEgSAQBIJAEAgCQSAIBIEgEASCQBAIAkEghHOegSAQBIJAEAgCQSAIBIEgEASCQBAIAkEgCASBIBAEgkAQmASBEM6TwJhOgkAQCAJBIAgEgSAQBIJAEAgCQSAIBIEgEASCQBAIAkEghHOegSAQBIJAEAgCQSAIBIEgEASCQBAIAkEgCASBIBAEgkAQmASBEM6TwJhOgkAQCAJBIAgEgSAQBIJAEAgCQSAIBIEgEASCQBAIAkEghHOegSAQBIJAEAgCQSAIBIEgEASCQBAIAkEgCASBIBAEgkAQmASBEM6TwJhOgkAQCAJBIAgEgSAQBIJAEAgCQSAIBIEgEASCQBAIAkEghHOegSAQBIJAEAgCQSAIBIEgEASCQBAIAkEgCASBIBAEgkAQmASBEM6TwJhOgkAQCAJBIAgEgSAQBIJAEAgCQSAIBIEgEASCQBAIAkEghHOegSAQBIJAEAgCQSAIBIEgEASCQBAIAkEgCASBIBAEgkAQmASBEM6TwJhOgkAQCAJBIAgEgSAQBIJAEAgCQSAIBIEgEASCQBAIAkEghHOegSAQBIJAEAgCQSAIBIEgEASCQBAIAkEgCASBIBAEgkAQmASBEM6TwJhOgkAQCAJBIAgEgSAQBIJAEAgCQSAIBIEgEASCQBAIAkEghHOegSAQBIJAEAgCQSAIBIEgEASCQBAIAkEgCASBIBAEgkAQmASBEM6TwJhOgkAQCAJBIAgEgSAQBIJAEAgCQSAIBIEgEASCQBAIAkEghHOegSAQBIJAEAgCQSAIBIEgEASCQBAIAkEgCASBIBAEgkAQmASBEM6TwJhOgkAQCAJBIAgEgSAQBIJAEAgCQSAIBIEgEASCQBAIAkEghHOegSAQBIJAEAgCQSAIBIEgEASCQBAIAkEgCASBIBAEgkAQmASB/wOpVU7Yw/lr4QAAAABJRU5ErkJggg==" + } + }, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "![image.png](attachment:image.png)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "如上图所示,当 f(5) 被调用之后,函数开始运行……\n", + "* 因为 `5 > 1`,所以,在计算 `n * f(n-1)` 的时候要再次调用自己 `f(4)`;所以必须等待 `f(4)` 的值返回;\n", + "* 因为 `4 > 1`,所以,在计算 `n * f(n-1)` 的时候要再次调用自己 `f(3)`;所以必须等待 `f(3)` 的值返回;\n", + "* 因为 `3 > 1`,所以,在计算 `n * f(n-1)` 的时候要再次调用自己 `f(2)`;所以必须等待 `f(2)` 的值返回;\n", + "* 因为 `2 > 1`,所以,在计算 `n * f(n-1)` 的时候要再次调用自己 `f(1)`;所以必须等待 `f(1)` 的值返回;\n", + "* 因为 `1 == 1`,所以,这时候不会再次调用 `f()` 了,`f(1)` 返回值是 `1`;\n", + "* 下一步,`f(2)` 返回值是 `2 * 1 = 2`;\n", + "* 下一步,`f(3)` 返回值是`3 * 2 = 6`;\n", + "* 下一步,`f(4)` 返回值是`4 * 6 = 24`;\n", + "* 下一步,`f(5)` 返回值是`5 * 24 = 120`。\n", + "\n", + "至此,函数调用 `f(5)` 才执行完,最终返回值是 `120`。这个调用中“**递归**(*recursively*)”调用了四次 `f()` 自己。\n", + "\n", + "> *Recursive* 本来就是“反复、重复”的意思。\n", + "\n", + "试着在自己脑子里把这个过程走通,有点烧脑,不过搞清楚了也很有意思。" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 递归的终止" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "从上面的例子,我们可以发现,最终 f(1) 不再需要递归,可以直接返回一个确定的值,这一步是递归的转折点,特别重要,如果没有这个,递归就会无穷无尽的重复下去,永远得不到结果,就像最开始我们写的那个老和尚讲故事的例子一样。\n", + "\n", + "把我们计算阶乘的例子中的 `if n == 1:` 条件去掉,直接写成这样:\n", + "\n", + "```python\n", + "def f(n):\n", + " return n * f(n-1)\n", + "```\n", + "\n", + "如果运行这个版本的 `f(5)`,会得到一个运行时异常 `RecursionError: maximum recursion depth exceeded`,因为 Python 对递归次数是有限制的,达到一定次数还没返回的递归会抛出这个异常。\n", + "\n", + "我们写递归函数的时候,要特别小心的确认递归的终止条件,就和循环中的退出条件一样,一定不能出现无限递归或者死循环的情况。" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 递归的好处与代价" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "从理论上可以证明,所有递归(*recursion*)都可以改写为循环(*iteration*),反之所有循环也都可以用递归改写。那么我们写递归这样的算法好处是什么呢?\n", + "\n", + "> Alonzo Church 和 Alan Turing 两位现代计算机科学的奠基者的[经典论文](https://en.wikipedia.org/wiki/Church%E2%80%93Turing_thesis)提供了证明,前提是内存管够。\n", + "\n", + "最大的好处是清晰易懂。递归通常用于本质上就带有递归特性的问题(如前面所见的例子),递归算法几乎原样展现了问题的本质,容易理解也容易编写。\n", + "\n", + "另外的好处是,对某些问题的算法,递归是最优化的,比如树型结构的遍历。\n", + "\n", + "凡事有得必有失。递归的代价是什么呢?\n", + "\n", + "主要代价有二:递归一般会使用更多的内存,因为每次调用自身都需要建立新函数调用所需要的环境,占用相应的资源,一直迭代到最深层开始返回才会释放这些资源,对此有些编程语言会在编译器和运行时进行优化,比如“**尾递归优化**(*tail-recursion optimization, TRO*)”,能够将这种消耗免除,但 Python 并不支持(以后也不会支持),所以 Python 会限制递归的层次,超过就扔出 `RecursiveError`。\n", + "\n", + "另一个代价是,有的时候递归算法不是最高效的,这涉及到算法分析,我们目前还不用深入,知道有这些代价就好。" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "对于我们来说,了解这种思考问题的方法,在碰到适合的问题时能多一个思路,就是相当不错的收获了。" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 小试身手" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "1. 使用递归求最大公约数 \n", + "(1)编写函数gcd(m,n),可以如下递归定义: \n", + "* 如果m%n为0,那么gcd(m,n)的值为n。\n", + "* 否则,gcd(m,n)的值是gcd(n,m%n)\n", + "(2)调用gcd函数,测试gcd的正确性\n" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "5\n" + ] + } + ], + "source": [ + "def gcd(m,n):\n", + " if m%n == 0:\n", + " return n\n", + " else:\n", + " return gcd(n,m%n)\n", + "print(gcd(15,25))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "2.使用递归方法逆序输出一个整数中的数字 \n", + "(1)编写函数reverseDisplay(value),可以如下递归定义: \n", + "* 如果value大于0,那么输出个位数,并继续递归调用reverseDisplay(value//10)\n", + "* 否则 函数结束 \n", + "\n", + "(2)调用reverseDisplay函数,测试reverseDisplay的正确性。 \n", + "\n", + "reverseDisplay(12345) \n", + "54321 " + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "54321" + ] + } + ], + "source": [ + "def reverseDisplay(value):\n", + " pass\n", + "reverseDisplay(12345)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "3.使用递归方法逆序输出一个字符串中的字母 \n", + "(1)编写函数reverseDisplay(s),可以如下递归定义: \n", + "\n", + "* 如果s的长度不等于1,那么s串去首字符,继续递归调用。 \n", + "* 输出字符串的首字符。\n", + "\n", + "(2)调用reverseDisplay函数,测试reverseDisplay的正确性。 \n", + "\n", + "reverseDisplay(\"abcde\") \n", + "edcba " + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "edcba" + ] + } + ], + "source": [ + "def reverseDisplay(s):\n", + " if len(s)!=1:\n", + " reverseDisplay(s[1:])\n", + " print(s[0],end=\"\")\n", + "reverseDisplay(\"abcde\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.10" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +}