计算机二级练习仓库
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

595 regels
16 KiB

2 jaren geleden
  1. {
  2. "cells": [
  3. {
  4. "cell_type": "markdown",
  5. "metadata": {},
  6. "source": [
  7. "# 实践3 函数与模块\n",
  8. "\n",
  9. "1. 理解函数的基本概念;\n",
  10. "2. 掌握Python内置函数的使用;\n",
  11. "3. 掌握Python标准模块的引入;\n",
  12. "4. 掌握math模块中常用数学函数的使用;\n",
  13. "5. 理解函数的定义和调用。"
  14. ]
  15. },
  16. {
  17. "cell_type": "markdown",
  18. "metadata": {},
  19. "source": [
  20. "## 1.函数"
  21. ]
  22. },
  23. {
  24. "cell_type": "markdown",
  25. "metadata": {},
  26. "source": [
  27. "程序里的函数概念完全来自数学里的函数。我们先来看看数学里的函数。"
  28. ]
  29. },
  30. {
  31. "cell_type": "markdown",
  32. "metadata": {},
  33. "source": [
  34. "### 函数的基本概念"
  35. ]
  36. },
  37. {
  38. "cell_type": "markdown",
  39. "metadata": {},
  40. "source": [
  41. "在数学里,我们可以定义一个函数,函数有一些*自变量*,也就是一些**输入**,**函数定义**就是定义如何通过这些输入计算出*函数的值*,也就是**输出**。下面是个典型的函数定义的例子:"
  42. ]
  43. },
  44. {
  45. "cell_type": "markdown",
  46. "metadata": {},
  47. "source": [
  48. "$\n",
  49. "\\begin{align}\n",
  50. "f(a, b) = \\sqrt{a^2 + b^2}\n",
  51. "\\end{align}\n",
  52. "$"
  53. ]
  54. },
  55. {
  56. "cell_type": "markdown",
  57. "metadata": {},
  58. "source": [
  59. "函数定义好之后,随时可以用具体的值送进去算出一个具体的函数值,比如:\n",
  60. "\n"
  61. ]
  62. },
  63. {
  64. "cell_type": "markdown",
  65. "metadata": {},
  66. "source": [
  67. "$\n",
  68. "\\begin{align}\n",
  69. "f(1, 2) = \\sqrt{5}\n",
  70. "\\end{align}\n",
  71. "$"
  72. ]
  73. },
  74. {
  75. "cell_type": "markdown",
  76. "metadata": {},
  77. "source": [
  78. "$\n",
  79. "\\begin{align}\n",
  80. "f(3, 4) = 5\n",
  81. "\\end{align}\n",
  82. "$"
  83. ]
  84. },
  85. {
  86. "cell_type": "markdown",
  87. "metadata": {},
  88. "source": [
  89. "$\n",
  90. "\\begin{align}\n",
  91. "f(2, 6) = 2\\sqrt{10}\n",
  92. "\\end{align}\n",
  93. "$"
  94. ]
  95. },
  96. {
  97. "cell_type": "markdown",
  98. "metadata": {},
  99. "source": [
  100. "程序里的函数也是这样,我们先要定义函数,也就是定义它的名字(叫做 **函数名** *function name*)、若干输入变量(叫做 **参数** *argument*)以及如何通过输入变量算出函数的值(叫做 **返回值** *return value*);一旦定义好,就可以在程序的其他地方随时使用这个函数,给它具体的参数值,它就给出具体的返回值。"
  101. ]
  102. },
  103. {
  104. "cell_type": "markdown",
  105. "metadata": {},
  106. "source": [
  107. "### 调用现成的函数"
  108. ]
  109. },
  110. {
  111. "cell_type": "markdown",
  112. "metadata": {},
  113. "source": [
  114. "我们先看看怎么用函数,术语叫做函数**调用**(*call*),因为 Python 本身自带了很多已经定义好的函数,我们可以直接拿来用。其中有一些我们之前已经用过了:\n",
  115. "* `print(a, b,...)`:在命令行输出界面打印输入的参数(可以是各种类型的数据);\n",
  116. "* `type(x)`:返回参数 x 的数据类型;\n",
  117. "* `abs(x)`:返回参数 x(整数或者浮点数)的绝对值。\n",
  118. "\n",
  119. "这几个都是 Python 的内置函数,可以直接用。我们下面来看两个其他的例子。"
  120. ]
  121. },
  122. {
  123. "cell_type": "markdown",
  124. "metadata": {},
  125. "source": [
  126. "第一个例子是另一个 Python 内置函数,叫做 `isinstance(x, c)`,它有两个输入参数,第一个是一个数据,第二个是一个数据类型,如果第一个数据是第二个数据类型,`isinstance` 函数返回 `True`,否则就返回 `False`。所以 `isinstance` 可以用来判断某个值或者变量是不是某种类型,下面是例子:"
  127. ]
  128. },
  129. {
  130. "cell_type": "code",
  131. "execution_count": 37,
  132. "metadata": {},
  133. "outputs": [
  134. {
  135. "data": {
  136. "text/plain": [
  137. "True"
  138. ]
  139. },
  140. "execution_count": 37,
  141. "metadata": {},
  142. "output_type": "execute_result"
  143. }
  144. ],
  145. "source": [
  146. "isinstance(a, int)"
  147. ]
  148. },
  149. {
  150. "cell_type": "code",
  151. "execution_count": 38,
  152. "metadata": {},
  153. "outputs": [
  154. {
  155. "data": {
  156. "text/plain": [
  157. "False"
  158. ]
  159. },
  160. "execution_count": 38,
  161. "metadata": {},
  162. "output_type": "execute_result"
  163. }
  164. ],
  165. "source": [
  166. "isinstance(a, float)"
  167. ]
  168. },
  169. {
  170. "cell_type": "code",
  171. "execution_count": 39,
  172. "metadata": {},
  173. "outputs": [
  174. {
  175. "data": {
  176. "text/plain": [
  177. "True"
  178. ]
  179. },
  180. "execution_count": 39,
  181. "metadata": {},
  182. "output_type": "execute_result"
  183. }
  184. ],
  185. "source": [
  186. "isinstance(g, float)"
  187. ]
  188. },
  189. {
  190. "cell_type": "code",
  191. "execution_count": 40,
  192. "metadata": {},
  193. "outputs": [
  194. {
  195. "data": {
  196. "text/plain": [
  197. "False"
  198. ]
  199. },
  200. "execution_count": 40,
  201. "metadata": {},
  202. "output_type": "execute_result"
  203. }
  204. ],
  205. "source": [
  206. "isinstance(True, str)"
  207. ]
  208. },
  209. {
  210. "cell_type": "code",
  211. "execution_count": 41,
  212. "metadata": {},
  213. "outputs": [
  214. {
  215. "data": {
  216. "text/plain": [
  217. "True"
  218. ]
  219. },
  220. "execution_count": 41,
  221. "metadata": {},
  222. "output_type": "execute_result"
  223. }
  224. ],
  225. "source": [
  226. "isinstance(True, bool)"
  227. ]
  228. },
  229. {
  230. "cell_type": "code",
  231. "execution_count": 42,
  232. "metadata": {},
  233. "outputs": [
  234. {
  235. "data": {
  236. "text/plain": [
  237. "True"
  238. ]
  239. },
  240. "execution_count": 42,
  241. "metadata": {},
  242. "output_type": "execute_result"
  243. }
  244. ],
  245. "source": [
  246. "isinstance('abracadabra', str)"
  247. ]
  248. },
  249. {
  250. "cell_type": "code",
  251. "execution_count": 43,
  252. "metadata": {},
  253. "outputs": [
  254. {
  255. "data": {
  256. "text/plain": [
  257. "True"
  258. ]
  259. },
  260. "execution_count": 43,
  261. "metadata": {},
  262. "output_type": "execute_result"
  263. }
  264. ],
  265. "source": [
  266. "isinstance(True, bool) and not isinstance('abracadabra', float)"
  267. ]
  268. },
  269. {
  270. "cell_type": "markdown",
  271. "metadata": {},
  272. "source": [
  273. "## 2.模块\n",
  274. "\n",
  275. "第二个例子是 Python 的平方根函数 `math.sqrt(x)`,这个函数前面有个 `math`,这表示函数 `sqrt(x)` 不在 Python 的内置环境中,而是放在一个叫 `math` 的函数包(学名叫 **模块** *module*)里,关于模块我们以后会专门介绍。要使用这种函数,第一种方法是:\n",
  276. "* 先 **引入**(*import*)对应的函数包;\n",
  277. "* 使用时函数名前面要带上模块的名字,中间加个 `.`。\n",
  278. "\n",
  279. "就像下面这样:"
  280. ]
  281. },
  282. {
  283. "cell_type": "code",
  284. "execution_count": 44,
  285. "metadata": {},
  286. "outputs": [
  287. {
  288. "data": {
  289. "text/plain": [
  290. "4.0"
  291. ]
  292. },
  293. "execution_count": 44,
  294. "metadata": {},
  295. "output_type": "execute_result"
  296. }
  297. ],
  298. "source": [
  299. "import math\n",
  300. "math.sqrt(16)"
  301. ]
  302. },
  303. {
  304. "cell_type": "markdown",
  305. "metadata": {},
  306. "source": [
  307. "另外一种方法是,从对应的模块里指明引入这一个函数,使用时就不用带上模块名了:"
  308. ]
  309. },
  310. {
  311. "cell_type": "code",
  312. "execution_count": 45,
  313. "metadata": {},
  314. "outputs": [
  315. {
  316. "data": {
  317. "text/plain": [
  318. "6.324555320336759"
  319. ]
  320. },
  321. "execution_count": 45,
  322. "metadata": {},
  323. "output_type": "execute_result"
  324. }
  325. ],
  326. "source": [
  327. "from math import sqrt\n",
  328. "sqrt(40)"
  329. ]
  330. },
  331. {
  332. "cell_type": "markdown",
  333. "metadata": {},
  334. "source": [
  335. "我们可以看到 `sqrt(x)` 函数可以接受整数或者浮点数输入,返回值是浮点数。"
  336. ]
  337. },
  338. {
  339. "cell_type": "markdown",
  340. "metadata": {},
  341. "source": [
  342. "## 3. 定义函数"
  343. ]
  344. },
  345. {
  346. "cell_type": "markdown",
  347. "metadata": {},
  348. "source": [
  349. "有了 `sqrt(x)` 这个函数,我们可以定义一个函数来实现前面举例的那个数学里的函数 `f(a, b)` 了。在 Python 里函数的定义以关键字 `def` 开始,后面依次是函数名、小括号括起来的参数列表和一个冒号,之后的代码就是函数的算法定义,直到关键字 `return` 开始的 **返回语句**,这个返回语句会终止函数的运行,并把 `return` 后面的值作为函数的返回值,回到调用函数的地方。看起来有点抽象,我们看看例子: "
  350. ]
  351. },
  352. {
  353. "cell_type": "code",
  354. "execution_count": 3,
  355. "metadata": {},
  356. "outputs": [
  357. {
  358. "name": "stdout",
  359. "output_type": "stream",
  360. "text": [
  361. "5.0\n"
  362. ]
  363. }
  364. ],
  365. "source": [
  366. "from math import sqrt\n",
  367. "\n",
  368. "def f(a, b):\n",
  369. " return sqrt(a**2 + b**2)\n",
  370. "\n",
  371. "result = f(3, 4)\n",
  372. "print(result)"
  373. ]
  374. },
  375. {
  376. "cell_type": "markdown",
  377. "metadata": {},
  378. "source": [
  379. "上面的代码很短,但是很重要,我们务必要搞懂这里的每一个细节。\n",
  380. "\n",
  381. "首先第一行是引入 `sqrt(x)` 函数,因为我们下面定义的函数要用到它。\n",
  382. "\n",
  383. "然后是函数定义 `def f(a, b):`,关键字 `def` 打头,后面是函数名 `f`、参数列表 `(a, b)` 和一个冒号,这表示函数 `f` 接受两个参数,一个叫 `a` 一个叫 `b`。下面一行就是**函数体**(*function body*),里面可以写很多东西,只要最后有一个 `return` 指明函数返回值就行,注意 Python 的函数可以没有返回值(`return` 后面什么都不写就行了),也可以返回多个值(`return` 后面写多个值,用逗号隔开)。\n",
  384. "\n",
  385. "我们这个例子因为很简单,就一句话就能搞定:函数返回值等于 a 平方加 b 平方再开方。注意函数体的代码缩进了一些,和其他的行都是顶着行首书写不一样,这是 Python 的缩进规则要求的,下面的插播会做出解释。\n",
  386. "\n",
  387. "然后是调用函数的例子,它是这么进行的:\n",
  388. "1. 首先用 3 和 4 作为参数来调用 `f()` 函数;\n",
  389. "2. 函数 `f()` 开始执行,把值 3 赋给参数变量 a,4 赋给 b,然后执行函数体;\n",
  390. "3. 函数体计算出返回值 5.0 并返回;\n",
  391. "4. 用返回值 5.0 替换掉 `f()` 的位置,相当于执行赋值 `result = 5.0`\n",
  392. "5. 用 5.0 作为参数值调用内置的 `print()` 函数,打印出 5.0(`print()` 没有返回值)。\n",
  393. "\n",
  394. "顺便说一句,熟练之后我们可以把后两行简化成一句 `print(f(3, 4))`,效果是完全一样的。"
  395. ]
  396. },
  397. {
  398. "cell_type": "markdown",
  399. "metadata": {},
  400. "source": [
  401. "### 插播:代码缩进"
  402. ]
  403. },
  404. {
  405. "cell_type": "markdown",
  406. "metadata": {},
  407. "source": [
  408. "所谓代码缩进就是一行代码不顶格写,而是在行首空若干格再写。缩进可以很多层,比如 Python 中第一层缩进空四格,第二层缩进空八格,第三层缩进空十二格,依此类推。程序员都喜欢用“**等宽字体**(*fix-width font*)”,就是因为等宽字体在缩进时非常整齐美观。\n",
  409. "\n",
  410. "缩进是为了让代码层次更加鲜明地呈现出来。比如上面函数定义的代码,函数体的部分是“隶属于”函数定义 `def` 语句的,是它的组成部分,所以缩进一层表示这个从属关系;而后面的函数调用则不是,所以最后两行不缩进,和 `def` 语句平齐,代表是同一层级的代码。\n",
  411. "\n",
  412. "在 Python 中缩进是强制的,如果不进行正确的缩进,比如如果函数体没有正确的缩进,解释器会因为找不到必须的部分而报错。\n",
  413. "\n",
  414. "目前主流的程序编辑器都提供了自动缩进、自动排版的功能,在 VSCode 和 Jupyter Notebook 中书写代码时大部分时候都会自动正确的缩进,所以很方便。\n",
  415. "\n",
  416. "对于初学者来说,知道有这么回事,然后多看,慢慢就会习惯成自然,和多听多看学语言是差不多的道理。"
  417. ]
  418. },
  419. {
  420. "cell_type": "markdown",
  421. "metadata": {},
  422. "source": [
  423. "## 4.函数的调用 \n",
  424. "函数定义后,未经调用,是不会执行的。需要时使用函数调用语句。 \n",
  425. "在函数调用的时候要求传递对应的值给形参,这个传递的值称为实际参数,简称实参。参数是可选的,也就是说函数可以不包括参数,例如:random.random() 就不包含参数。 \n",
  426. "根据函数是否有返回值,函数的调用也是不同的。如果函数有返回值,函数调用的时候需要安排接受返回值。 \n",
  427. "\n"
  428. ]
  429. },
  430. {
  431. "cell_type": "code",
  432. "execution_count": 4,
  433. "metadata": {},
  434. "outputs": [
  435. {
  436. "data": {
  437. "text/plain": [
  438. "6.324555320336759"
  439. ]
  440. },
  441. "execution_count": 4,
  442. "metadata": {},
  443. "output_type": "execute_result"
  444. }
  445. ],
  446. "source": [
  447. "# 可以是赋值语句,将返回值赋值给一个变量\n",
  448. "z = f(2,6)\n",
  449. "z"
  450. ]
  451. },
  452. {
  453. "cell_type": "code",
  454. "execution_count": 5,
  455. "metadata": {},
  456. "outputs": [
  457. {
  458. "data": {
  459. "text/plain": [
  460. "50.0"
  461. ]
  462. },
  463. "execution_count": 5,
  464. "metadata": {},
  465. "output_type": "execute_result"
  466. }
  467. ],
  468. "source": [
  469. "# 可以是表达式语句,将返回值作为表达式的一个数值,继续参加运算\n",
  470. "z = f(3,4)*10\n",
  471. "z\n"
  472. ]
  473. },
  474. {
  475. "cell_type": "code",
  476. "execution_count": 6,
  477. "metadata": {},
  478. "outputs": [
  479. {
  480. "data": {
  481. "text/plain": [
  482. "11.180339887498949"
  483. ]
  484. },
  485. "execution_count": 6,
  486. "metadata": {},
  487. "output_type": "execute_result"
  488. }
  489. ],
  490. "source": [
  491. "# 可以作为函数调用的实参\n",
  492. "z=f(f(3,4),10)\n",
  493. "z\n"
  494. ]
  495. },
  496. {
  497. "cell_type": "markdown",
  498. "metadata": {},
  499. "source": [
  500. "### 函数的意义"
  501. ]
  502. },
  503. {
  504. "cell_type": "markdown",
  505. "metadata": {},
  506. "source": [
  507. "函数是编程中最重要的概念之一。实现它有助于我们实现程序的“**模块化**(*modulization*)”,我们可以把特定的工作用一个函数来实现,然后在需要的地方反复地调用它。这是一种代码重用的方法,一个函数就好像乐高积木里的一个组件,我们可以通过组合各种不同功能的函数来实现复杂的目标。\n",
  508. "\n",
  509. "函数还是协作编程的基础。如果我们实现了一个很有用的函数,我们可以写一个文档说明函数的输入参数和返回值是什么,这样的文档叫做**调用接口**(*interface*),别人都可以照此使用我们写的函数,甚至不需要了解它是怎么实现的(比如我们就直接拿了 `math.sqrt()` 来用而不需要自己写一个)。函数天生就把自己的接口和实现分离开,让协作和复用成果更容易。\n",
  510. "\n",
  511. "**模块化** 和 **接口独立** 是编程时最重要的两个思维模型(没有之一),我们在后面还会深入介绍。"
  512. ]
  513. },
  514. {
  515. "cell_type": "markdown",
  516. "metadata": {},
  517. "source": [
  518. "## 小试身手\n"
  519. ]
  520. },
  521. {
  522. "cell_type": "markdown",
  523. "metadata": {},
  524. "source": [
  525. "### (1)使用math模块的数学函数。 \n",
  526. "导入数学库math。然后输入以下表达式理解math中函数的使用,注意结果值的数据类型。 \n",
  527. "math.sqrt(2*2+3*3)、 math.log10(100)、 math.exp(2)、math.fmod(4,3)、math.sin(2*math.pi)、\n",
  528. "math.gcd(12,9)\n"
  529. ]
  530. },
  531. {
  532. "cell_type": "code",
  533. "execution_count": null,
  534. "metadata": {},
  535. "outputs": [],
  536. "source": []
  537. },
  538. {
  539. "cell_type": "markdown",
  540. "metadata": {},
  541. "source": [
  542. "[数学库math](https://docs.python.org/zh-cn/3/library/math.html)"
  543. ]
  544. },
  545. {
  546. "cell_type": "markdown",
  547. "metadata": {},
  548. "source": [
  549. "### (2)自定义求矩形面积的函数"
  550. ]
  551. },
  552. {
  553. "cell_type": "code",
  554. "execution_count": null,
  555. "metadata": {},
  556. "outputs": [],
  557. "source": [
  558. "#定义一个函数getArea(length,width),计算长为length,宽为width的矩形面积。 \n",
  559. "\n",
  560. "\n"
  561. ]
  562. },
  563. {
  564. "cell_type": "code",
  565. "execution_count": null,
  566. "metadata": {},
  567. "outputs": [],
  568. "source": [
  569. "#试着用不同的方式调用getArea函数,验证函数的正确性\n",
  570. "\n"
  571. ]
  572. }
  573. ],
  574. "metadata": {
  575. "kernelspec": {
  576. "display_name": "Python 3 (ipykernel)",
  577. "language": "python",
  578. "name": "python3"
  579. },
  580. "language_info": {
  581. "codemirror_mode": {
  582. "name": "ipython",
  583. "version": 3
  584. },
  585. "file_extension": ".py",
  586. "mimetype": "text/x-python",
  587. "name": "python",
  588. "nbconvert_exporter": "python",
  589. "pygments_lexer": "ipython3",
  590. "version": "3.9.5"
  591. }
  592. },
  593. "nbformat": 4,
  594. "nbformat_minor": 4
  595. }