计算机二级练习仓库
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 lines
16 KiB

{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 实践3 函数与模块\n",
"\n",
"1. 理解函数的基本概念;\n",
"2. 掌握Python内置函数的使用;\n",
"3. 掌握Python标准模块的引入;\n",
"4. 掌握math模块中常用数学函数的使用;\n",
"5. 理解函数的定义和调用。"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 1.函数"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"程序里的函数概念完全来自数学里的函数。我们先来看看数学里的函数。"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 函数的基本概念"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"在数学里,我们可以定义一个函数,函数有一些*自变量*,也就是一些**输入**,**函数定义**就是定义如何通过这些输入计算出*函数的值*,也就是**输出**。下面是个典型的函数定义的例子:"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"$\n",
"\\begin{align}\n",
"f(a, b) = \\sqrt{a^2 + b^2}\n",
"\\end{align}\n",
"$"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"函数定义好之后,随时可以用具体的值送进去算出一个具体的函数值,比如:\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"$\n",
"\\begin{align}\n",
"f(1, 2) = \\sqrt{5}\n",
"\\end{align}\n",
"$"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"$\n",
"\\begin{align}\n",
"f(3, 4) = 5\n",
"\\end{align}\n",
"$"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"$\n",
"\\begin{align}\n",
"f(2, 6) = 2\\sqrt{10}\n",
"\\end{align}\n",
"$"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"程序里的函数也是这样,我们先要定义函数,也就是定义它的名字(叫做 **函数名** *function name*)、若干输入变量(叫做 **参数** *argument*)以及如何通过输入变量算出函数的值(叫做 **返回值** *return value*);一旦定义好,就可以在程序的其他地方随时使用这个函数,给它具体的参数值,它就给出具体的返回值。"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 调用现成的函数"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"我们先看看怎么用函数,术语叫做函数**调用**(*call*),因为 Python 本身自带了很多已经定义好的函数,我们可以直接拿来用。其中有一些我们之前已经用过了:\n",
"* `print(a, b,...)`:在命令行输出界面打印输入的参数(可以是各种类型的数据);\n",
"* `type(x)`:返回参数 x 的数据类型;\n",
"* `abs(x)`:返回参数 x(整数或者浮点数)的绝对值。\n",
"\n",
"这几个都是 Python 的内置函数,可以直接用。我们下面来看两个其他的例子。"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"第一个例子是另一个 Python 内置函数,叫做 `isinstance(x, c)`,它有两个输入参数,第一个是一个数据,第二个是一个数据类型,如果第一个数据是第二个数据类型,`isinstance` 函数返回 `True`,否则就返回 `False`。所以 `isinstance` 可以用来判断某个值或者变量是不是某种类型,下面是例子:"
]
},
{
"cell_type": "code",
"execution_count": 37,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"True"
]
},
"execution_count": 37,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"isinstance(a, int)"
]
},
{
"cell_type": "code",
"execution_count": 38,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"False"
]
},
"execution_count": 38,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"isinstance(a, float)"
]
},
{
"cell_type": "code",
"execution_count": 39,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"True"
]
},
"execution_count": 39,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"isinstance(g, float)"
]
},
{
"cell_type": "code",
"execution_count": 40,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"False"
]
},
"execution_count": 40,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"isinstance(True, str)"
]
},
{
"cell_type": "code",
"execution_count": 41,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"True"
]
},
"execution_count": 41,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"isinstance(True, bool)"
]
},
{
"cell_type": "code",
"execution_count": 42,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"True"
]
},
"execution_count": 42,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"isinstance('abracadabra', str)"
]
},
{
"cell_type": "code",
"execution_count": 43,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"True"
]
},
"execution_count": 43,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"isinstance(True, bool) and not isinstance('abracadabra', float)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 2.模块\n",
"\n",
"第二个例子是 Python 的平方根函数 `math.sqrt(x)`,这个函数前面有个 `math`,这表示函数 `sqrt(x)` 不在 Python 的内置环境中,而是放在一个叫 `math` 的函数包(学名叫 **模块** *module*)里,关于模块我们以后会专门介绍。要使用这种函数,第一种方法是:\n",
"* 先 **引入**(*import*)对应的函数包;\n",
"* 使用时函数名前面要带上模块的名字,中间加个 `.`。\n",
"\n",
"就像下面这样:"
]
},
{
"cell_type": "code",
"execution_count": 44,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"4.0"
]
},
"execution_count": 44,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"import math\n",
"math.sqrt(16)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"另外一种方法是,从对应的模块里指明引入这一个函数,使用时就不用带上模块名了:"
]
},
{
"cell_type": "code",
"execution_count": 45,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"6.324555320336759"
]
},
"execution_count": 45,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from math import sqrt\n",
"sqrt(40)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"我们可以看到 `sqrt(x)` 函数可以接受整数或者浮点数输入,返回值是浮点数。"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 3. 定义函数"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"有了 `sqrt(x)` 这个函数,我们可以定义一个函数来实现前面举例的那个数学里的函数 `f(a, b)` 了。在 Python 里函数的定义以关键字 `def` 开始,后面依次是函数名、小括号括起来的参数列表和一个冒号,之后的代码就是函数的算法定义,直到关键字 `return` 开始的 **返回语句**,这个返回语句会终止函数的运行,并把 `return` 后面的值作为函数的返回值,回到调用函数的地方。看起来有点抽象,我们看看例子: "
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"5.0\n"
]
}
],
"source": [
"from math import sqrt\n",
"\n",
"def f(a, b):\n",
" return sqrt(a**2 + b**2)\n",
"\n",
"result = f(3, 4)\n",
"print(result)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"上面的代码很短,但是很重要,我们务必要搞懂这里的每一个细节。\n",
"\n",
"首先第一行是引入 `sqrt(x)` 函数,因为我们下面定义的函数要用到它。\n",
"\n",
"然后是函数定义 `def f(a, b):`,关键字 `def` 打头,后面是函数名 `f`、参数列表 `(a, b)` 和一个冒号,这表示函数 `f` 接受两个参数,一个叫 `a` 一个叫 `b`。下面一行就是**函数体**(*function body*),里面可以写很多东西,只要最后有一个 `return` 指明函数返回值就行,注意 Python 的函数可以没有返回值(`return` 后面什么都不写就行了),也可以返回多个值(`return` 后面写多个值,用逗号隔开)。\n",
"\n",
"我们这个例子因为很简单,就一句话就能搞定:函数返回值等于 a 平方加 b 平方再开方。注意函数体的代码缩进了一些,和其他的行都是顶着行首书写不一样,这是 Python 的缩进规则要求的,下面的插播会做出解释。\n",
"\n",
"然后是调用函数的例子,它是这么进行的:\n",
"1. 首先用 3 和 4 作为参数来调用 `f()` 函数;\n",
"2. 函数 `f()` 开始执行,把值 3 赋给参数变量 a,4 赋给 b,然后执行函数体;\n",
"3. 函数体计算出返回值 5.0 并返回;\n",
"4. 用返回值 5.0 替换掉 `f()` 的位置,相当于执行赋值 `result = 5.0`\n",
"5. 用 5.0 作为参数值调用内置的 `print()` 函数,打印出 5.0(`print()` 没有返回值)。\n",
"\n",
"顺便说一句,熟练之后我们可以把后两行简化成一句 `print(f(3, 4))`,效果是完全一样的。"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 插播:代码缩进"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"所谓代码缩进就是一行代码不顶格写,而是在行首空若干格再写。缩进可以很多层,比如 Python 中第一层缩进空四格,第二层缩进空八格,第三层缩进空十二格,依此类推。程序员都喜欢用“**等宽字体**(*fix-width font*)”,就是因为等宽字体在缩进时非常整齐美观。\n",
"\n",
"缩进是为了让代码层次更加鲜明地呈现出来。比如上面函数定义的代码,函数体的部分是“隶属于”函数定义 `def` 语句的,是它的组成部分,所以缩进一层表示这个从属关系;而后面的函数调用则不是,所以最后两行不缩进,和 `def` 语句平齐,代表是同一层级的代码。\n",
"\n",
"在 Python 中缩进是强制的,如果不进行正确的缩进,比如如果函数体没有正确的缩进,解释器会因为找不到必须的部分而报错。\n",
"\n",
"目前主流的程序编辑器都提供了自动缩进、自动排版的功能,在 VSCode 和 Jupyter Notebook 中书写代码时大部分时候都会自动正确的缩进,所以很方便。\n",
"\n",
"对于初学者来说,知道有这么回事,然后多看,慢慢就会习惯成自然,和多听多看学语言是差不多的道理。"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 4.函数的调用 \n",
"函数定义后,未经调用,是不会执行的。需要时使用函数调用语句。 \n",
"在函数调用的时候要求传递对应的值给形参,这个传递的值称为实际参数,简称实参。参数是可选的,也就是说函数可以不包括参数,例如:random.random() 就不包含参数。 \n",
"根据函数是否有返回值,函数的调用也是不同的。如果函数有返回值,函数调用的时候需要安排接受返回值。 \n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"6.324555320336759"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# 可以是赋值语句,将返回值赋值给一个变量\n",
"z = f(2,6)\n",
"z"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"50.0"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# 可以是表达式语句,将返回值作为表达式的一个数值,继续参加运算\n",
"z = f(3,4)*10\n",
"z\n"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"11.180339887498949"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# 可以作为函数调用的实参\n",
"z=f(f(3,4),10)\n",
"z\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 函数的意义"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"函数是编程中最重要的概念之一。实现它有助于我们实现程序的“**模块化**(*modulization*)”,我们可以把特定的工作用一个函数来实现,然后在需要的地方反复地调用它。这是一种代码重用的方法,一个函数就好像乐高积木里的一个组件,我们可以通过组合各种不同功能的函数来实现复杂的目标。\n",
"\n",
"函数还是协作编程的基础。如果我们实现了一个很有用的函数,我们可以写一个文档说明函数的输入参数和返回值是什么,这样的文档叫做**调用接口**(*interface*),别人都可以照此使用我们写的函数,甚至不需要了解它是怎么实现的(比如我们就直接拿了 `math.sqrt()` 来用而不需要自己写一个)。函数天生就把自己的接口和实现分离开,让协作和复用成果更容易。\n",
"\n",
"**模块化** 和 **接口独立** 是编程时最重要的两个思维模型(没有之一),我们在后面还会深入介绍。"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 小试身手\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### (1)使用math模块的数学函数。 \n",
"导入数学库math。然后输入以下表达式理解math中函数的使用,注意结果值的数据类型。 \n",
"math.sqrt(2*2+3*3)、 math.log10(100)、 math.exp(2)、math.fmod(4,3)、math.sin(2*math.pi)、\n",
"math.gcd(12,9)\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"[数学库math](https://docs.python.org/zh-cn/3/library/math.html)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### (2)自定义求矩形面积的函数"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#定义一个函数getArea(length,width),计算长为length,宽为width的矩形面积。 \n",
"\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#试着用不同的方式调用getArea函数,验证函数的正确性\n",
"\n"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"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.9.5"
}
},
"nbformat": 4,
"nbformat_minor": 4
}