文章目录
- 一. 函数的定义和使用
- 1. 函数的理解与定义
- (1). 定义
- (2). 作用
- (3). 函数分类
- (3). 基本语法
- 2. 函数的使用及调用过程
- (1). 函数的调用
- 1. 调用函数的语法格式:
- 2. 调用是运行函数代码的方式
- (2). 函数调用过程
- 3. 函数的参数传递
- (1). 参数个数
- (2). 可选参数传递
- (3). 可变参数传递(带有*号的参数)
- 1. 定义
- 2. 带有一个*号的参数的基本语法:
- 3. 带有两个*号的参数的基本语法:
- (4). 参数传递的两种方式
- 方式一:位置传递
- 方式二:名称传递
- (5). 形参和实参的讨论
- 4. 函数的返回值
- 5. 局部变量和全局变量
- (1). 定义
- (2). 使用规则
- 1. 规则一:局部变量和全局变量是不同的变量
- 2. 规则二:局部变量为组合数据类型且未创建,等同于全局变量
- 6. lambda函数
- (1). 定义
- (2). 语法格式:
- (3). 谨慎使用lambda函数
- 7. 七段数码管的绘制
- (1). 基本思路
- 二. 代码复用与函数递归
- 1. 代码复用与模块化设计
- (1). 把代码当成资源进行抽象
- (2). 函数和对象是代码复用的两种主要形式
- (3). 模块化设计
- 1. **分而治之**
- 2. 紧耦合、松耦合
- 2. 函数递归的理解
- (1). 递归定义:函数定义中调用函数自身的方式
- (2). 两个关键特性
- (3). 数学归纳法
- 3. 函数递归的调用过程
- (1). 举例
- (2). 递归的实现
- (3). 递归的调用过程
- 4. 函数递归实例解析
- (1). 字符串反转
- (2). 斐波那契数列
- (3). 汉罗塔
- (4). 科赫雪花
- 1. 分形几何
- 2. 用Python绘制科赫曲线
- 3. 科赫曲线绘制函数
- 4. 科赫雪花代码
一. 函数的定义和使用
1. 函数的理解与定义
(1). 定义
数学中的函数:表示从自变量到因变量之间的一种映射和对应关系
程序设计中的函数也有类似含义,就是把输入经过一定的变化和处理最后得到预定的输出。
函数是一段代码的表示
函数是一段具有特定功能的、可重用的语句组
函数是一种功能的抽象,一般函数表达特定功能
(2). 作用
降低编码难度
代码复用
代码整洁,易于理解
(3). 函数分类
- 内置函数
Python内置了若干常用函数,程序中直接使用
abs()
len()
- 标准库函数
安装Python语言解释器的同时会安装若干标准库函数,通过import导入
math()
random()
- 第三方库函数
Python社区提供许多高质量的库,通过import语句导入
jieba
numpy
requests
- 用户自定义函数
用户自己定义并使用的函数
(3). 基本语法
在Python中,定义函数语法格式:
def 函数名([形参1,形参2,... ]):
函数体
return 返回值
注:
函数体可以使用多个return语句,一旦第一条return语句得到执行,函数立即终止。
return语句可以出现在函数的任何位置。
2. 函数的使用及调用过程
(1). 函数的调用
1. 调用函数的语法格式:
函数名(实参1,实参2,... )
注意:
- 实参在程序运行时,实际传递给函数的数据
- 实参列表与函数定义时的形参列表一一对应
- 函数如果有返回值,则可以在表达式中继续使用
- 函数没有返回值,可以单独作为表达式语句使用
2. 调用是运行函数代码的方式
(2). 函数调用过程
3. 函数的参数传递
函数有以下几种方式将实际参数传递给形式参数:
(1). 参数个数
函数可以有参数,也可以没有,但必须保留括号
基本语法:
def 函数名():
函数体
return 返回值
(2). 可选参数传递
函数定义时可以为某些参数指定默认值,构成可选参数
在调用该函数时,如果没有传入对应的实参值,则函数使用声明的默认值参数。
基本语法:
def 函数名(非可选参数, 可选参数=默认值, ... ):
函数体
return 返回值
注:必选参数必须要写在可选参数的前面
因为函数调用的时候,默认是按位置传递实际参数的
(3). 可变参数传递(带有*号的参数)
1. 定义
函数定义时可以设计可变数量参数,即不确定参数总数,
意味着允许向函数传递可变数量的参数
2. 带有一个*号的参数的基本语法:
def 函数名(*可变参数):
函数体
return 返回值
注:从该参数之后的所有的参数都被收集为一个元组
3. 带有两个*号的参数的基本语法:
def 函数名(*可变参数):
函数体
return 返回值
注:调用函数时,从该参数之后所有的参数都被收集为一个字典。
def commonMultiple(**d):
total = 0
print(d)
for key in d:
total += d[key]
return total
print(commonMultiple(group1=5, group2=20, group3=14, group4=22))
print(commonMultiple(male=5, female=12))
结果:
{'group1': 5, 'group2': 20, 'group3': 14, 'group4': 22}
61
{'male': 5, 'female': 12}
17
(4). 参数传递的两种方式
函数调用时,参数可以按照位置或名称方式传递
方式一:位置传递
函数调用时,实参默认按照位置顺序传递参数,按照位置传递的参数称为位置参数
方式二:名称传递
通过名称(关键字)指定传入的参数,按照名称指定传入的参数称为名称参数
名称传递参数的优点
- 参数意义明确
- 传递的参数与顺序无关
- 如果有多个可选参数,则可以选择指定某个参数值
(5). 形参和实参的讨论
当实参是可变对象类型时,形参将会是该可变对象类型的引用,而不是创建新的类型对象,所以在函数中可以直接修改可变类型对象元素的值
可变对象:列表、字典
不可变对象:整型、浮点型、字符串类型、布尔类型
4. 函数的返回值
- return保留字用来传递返回值
- 函数可以有返回值,也可以没有,可以有return,也可以没有
- return可以传递0个返回值,也可以传递任意多个返回值
注:如果需要返回多个值,则可以返回一个元组
5. 局部变量和全局变量
(1). 定义
一个程序中的所有变量并不是在任何位置都可以被访问。访问权限取决于这个变量是在哪里赋值的。每个变量都有自己的作用域,变量的作用域决定了在某些diam段内使用该变量是合法的,在某些代码段内使用是不合法的。
最基本的变量作用域:
- 局部变量
- 全局变量
(2). 使用规则
注:基本数据类型,无论是否重名,局部变量与全局变量不同
在局部变量(包括形参)和全局变量同名时,局部变量屏蔽全局变量,检测局部优先。
1. 规则一:局部变量和全局变量是不同的变量
2. 规则二:局部变量为组合数据类型且未创建,等同于全局变量
6. lambda函数
(1). 定义
- lambda函数是一种匿名函数,即没有名字的函数
- 使用lambda保留字定义,函数名是返回结果
- lambda函数用于定义简单的、能够在一行内表示的函数
(2). 语法格式:
lambda 参数1, 参数2,....:<函数语句>
其中函数语句的结果为函数的返回值,且只能是一条语句
(3). 谨慎使用lambda函数
- lambda函数主要用作一些特定函数或方法的参数
- lambda函数有一些固定使用方式
- 一般情况下,建议使用def定义普通的函数
7. 七段数码管的绘制
(1). 基本思路
- 步骤一:绘制单个数字对应的数码管
- 步骤二:获得一串数字,绘制对应的数码管
- 步骤三:获得当前系统时间,绘制对应的数码管
import turtle
def drawLine(draw):
turtle.pendown() if draw else turtle.penup()
turtle.fd(40)
turtle.right(90)
def drawDigit(digit):
drawLine(True) if digit in [2,3,4,5,6,8,9] else drawLine(False)
drawLine(True) if digit in [0,1,3,4,5,6,7,8,9] else drawLine(False)
drawLine(True) if digit in [0,2,3,5,6,8,9] else drawLine(False)
drawLine(True) if digit in [0,2,6,8] else drawLine(False)
turtle.left(90)
drawLine(True) if digit in [0,4,5,6,8,9] else drawLine(False)
drawLine(True) if digit in [0,2,3,5,6,7,8,9] else drawLine(False)
drawLine(True) if digit in [0,1,2,3,4,7,8,9] else drawLine(False)
turtle.left(180)
turtle.penup()
turtle.fd(20)
def drawDate(date):
for i in date:
drawDigit(eval(i))
def main():
turtle.setup(800, 350, 200, 200)
turtle.penup()
turtle.fd(-300)
turtle.pensize(5)
drawDate('20201026')
turtle.hideturtle()
turtle.done()
main()
import turtle, time
def drawLine(draw):
turtle.pendown() if draw else turtle.penup()
turtle.fd(40)
turtle.right(90)
def drawDigit(digit):
drawLine(True) if digit in [2,3,4,5,6,8,9] else drawLine(False)
drawLine(True) if digit in [0,1,3,4,5,6,7,8,9] else drawLine(False)
drawLine(True) if digit in [0,2,3,5,6,8,9] else drawLine(False)
drawLine(True) if digit in [0,2,6,8] else drawLine(False)
turtle.left(90)
drawLine(True) if digit in [0,4,5,6,8,9] else drawLine(False)
drawLine(True) if digit in [0,2,3,5,6,7,8,9] else drawLine(False)
drawLine(True) if digit in [0,1,2,3,4,7,8,9] else drawLine(False)
turtle.left(180)
turtle.penup()
turtle.fd(20)
def drawDate(date):
turtle.pencolor("red")
for i in date:
if i == '-':
turtle.write('年', font=("Arial", 18, "normal"))
turtle.pencolor("green")
turtle.fd(40)
elif i == "=":
turtle.write('月', font=("Arial", 18, "normal"))
turtle.pencolor("blue")
turtle.fd(40)
elif i == '+':
turtle.write('日', font=("Arial", 18, "normal"))
else:
drawDigit(eval(i))
def main():
turtle.setup(800, 350, 200, 200)
turtle.penup()
turtle.fd(-300)
turtle.pensize(5)
drawDate(time.strftime('%Y-%m=%d+',time.gmtime()))
turtle.hideturtle()
turtle.done()
main()
二. 代码复用与函数递归
1. 代码复用与模块化设计
(1). 把代码当成资源进行抽象
- 代码资源化:程序代码是一种用来表达计算的资源
- 代码抽象化:使用函数等方法对代码赋予更高级别的定义
- 代码复用:同一份代码在需要时可以被重复使用
(2). 函数和对象是代码复用的两种主要形式
(3). 模块化设计
1. 分而治之
- 通过函数或对象封装将程序划分为模块及模块间的表达
- 具体包括:主程序、子程序和子程序间关系
- 分而治之:一种分而治之、分层抽象、体系化的设计思想
2. 紧耦合、松耦合
- 紧耦合:两个部分之间交流多,无法独立存在
- 松耦合:两个部分之间交流较少,可以独立存在
- 模块内部紧耦合、模块之间松耦合
2. 函数递归的理解
(1). 递归定义:函数定义中调用函数自身的方式
Python语言中,一个函数既可以调用另一个函数,也可以调用它自己。
如果一个函数调用了它自己,就称为递归
(2). 两个关键特性
- 终止条件:表示递归的结束条件,用于返回函数值,不再递归调用
- 递归步骤:递归步骤把第n步的函数与第n-1步的函数关联
(3). 数学归纳法
3. 函数递归的调用过程
(1). 举例
(2). 递归的实现
函数+分支语句
- 递归本身是一个函数,需要函数定义方式描述
- 函数内部,采用分支语句对输入参数进行判断
- 基例和链条,分别编写对应的代码
(3). 递归的调用过程
4. 函数递归实例解析
(1). 字符串反转
(2). 斐波那契数列
(3). 汉罗塔
(4). 科赫雪花
1. 分形几何
2. 用Python绘制科赫曲线
3. 科赫曲线绘制函数
4. 科赫雪花代码
import turtle
def koch(size, n):
if n == 0:
turtle.fd(size)
else:
for angle in [0, 60, -120, 60]:
turtle.left(angle)
koch(size/3, n-1)
def main():
turtle.setup(600,600)
turtle.penup()
turtle.goto(-200, 100)
turtle.pendown()
turtle.pensize(2)
# koch(600, 3) #3阶科赫曲线,阶数
level = 3 # 代表雪花的阶数
koch(400, level)
turtle.right(120)
koch(400, level)
turtle.right(120)
koch(400, level)
turtle.hideturtle()
turtle.done()
main()