1、函数的定义
制作一杯就要写 5 行代码,制作 3 杯的话,要写 15 行代码,而且内容都一样!决心要成为 Python 大神的你,怎么能忍受这么低效的方式呢!根据 DRY (Don't repeat yourself) 原则,我们写代码才不会做这种无聊的事情。
我们不妨换一种聪明的方法:在一开始,就把某件事情的步骤教给 Python,并用一句“暗号”来指代要让 Python 做的事情,以后只要对 Python 说出这个“暗号”,Python 就能把整个事情做完。
先来教 Python 自己做猕猴桃汁,并把“暗号”定为 make_juice
。教 Python 做果汁的代码要这样写:
def make_juice():
print('将猕猴桃去皮')
print('将猕猴桃切块')
print('将切碎的猕猴桃放进榨汁机')
print('将果汁倒进杯子中')
print('制作完成!')
def
是 define(中文含义:定义)的缩写,表示你要向 Python 传授做事流程了,make_juice
是你定义的流程暗号名。在这一行的末尾,一定要加上一对 英文括号 和一个 英文冒号 哦。
这样,Python 就记住了, make_juice
是它学会的“新暗号”,专门用来制作猕猴桃汁。以后,我们只要使用 暗号名()
的格式,就能让 Python 进行我们刚刚教会它的一系列操作。
make_juice()
make_juice()
make_juice()
# 前 6 行教会 Python 做猕猴桃汁
def make_juice():
print('将猕猴桃去皮')
print('将猕猴桃切块')
print('将切碎的猕猴桃放进榨汁机')
print('将果汁倒进杯子中')
print('制作完成!')
# 缩进结束,表示定义完毕
# 后 3 行用 Python 做三杯猕猴桃汁
make_juice()
make_juice()
make_juice()
前面教 Python 做事,并设定好“暗号”的过程,叫作 定义函数。其中缩进的几行表示具体处理过程的代码,叫 函数体
2、函数的参数
仔细想想,榨果汁,其实就是“流水的原料,铁打的步骤”。水果不管怎么变,都是要去皮、切块、放进榨汁机的。所以我们需要对函数进行改造,让它对所有水果都通用。
我们可以预设一个临时变量 fruit
,表示将要处理的水果,放进函数的定义过程中,让 Python 学习更灵活的做事流程。
# 定义函数时,括号中写进预设的变量 fruit
def make_juice(fruit):
# 把 fruit 写进函数体中
print('将' + fruit + '去皮')
print('将' + fruit + '切块')
print('将切碎的' + fruit + '放进榨汁机')
print('将果汁倒进杯子中')
print('制作完成!')
# 做苹果汁
make_juice('苹果')
# 做桃子汁
make_juice('桃子')
预设的临时变量 fruit
,要放进第 1 行定义函数部分的括号中,用以向 Python 事先声明,具体的水果需要视情况而定;在函数体中,水果该出现的地方也换成 fruit
。定义完毕后,Python 虽然不知道到底要遇到什么水果,但至少是把流程给牢牢记住了。
等到读到下面的调用函数的代码 make_juice('苹果')
时,Python 就恍然大悟:“我要把 '苹果'
赋值给 fruit
,然后再执行代码
定义函数时预设的临时变量,有个专门的名称:参数。定义过程所用的样板 fruit
,叫作 形式参数,简称 形参,只起示范作用;而实际调用函数时 make_juice('桃子')
中的 '桃子'
,叫作 实际参数,简称 实参
3、函数的返回值(return语句)
def circle(r):
c = 2 * 3.14 * r
result = circle(2)
print(result)
打印的结果是 None
在 Python 中,None
是一个特殊的值,表示“什么也没有”,在这里,表示变量 result
是空的,没有任何值,硬要通过 print(result)
打印的话,就只能打印出 None
通知你一下,“不要问,问就是没有”。
函数内部的代码是一个封闭的“小团体”,不管里面的代码运行出了什么,都不会主动和外面的代码分享。就算函数体里面加个 print()
,也只是把结果打印在屏幕上而已,不会和别的代码互通有无。也就是说,除了打印,毫无用处,无法进行其它操作。
这时候,我们需要在函数内部的结尾,加上 return
语句来帮忙,它的作用就是函数内部与外部世界的“信使”,负责将函数内部的值传递给外面
def circle(r):
c = 2 * 3.14 * r
# 函数体最后一行加上 return 语句
return c
result = circle(2)
print(result)
print('该圆的周长为' + str(result))
函数体中, return c
的意思是,将 c
指定为唯一可以和外界交流的数据,外面的代码想要获取内部运行结果,就丢个 c
的值给他。至于外面如何处置,函数就管不着了。
被 return
语句传到函数外的值,叫作函数的 返回值。返回值 要么被外部代码直接打印,要么赋值给变量,要么参与运算等。总之,每一次 circle()
函数的调用,都会和其它代码联系在一起,而 返回值 c
就是唯一的纽带
def circle(r):
c = 2 * 3.14 * r
# 函数体最后一行加上 return 语句
return c
# 直接打印返回值
print(circle(1))
# 输出:6.28
# 将返回值赋值给变量
result = circle(3)
print(result)
# 输出:18.84
# 返回值参与运算
print(circle(1) * -1)
# 输出:-6.28
# 返回值参与字符串的拼接
print('本次的运算结果为' + str(circle(1)))
# 输出:本次的运算结果为6.28
# 定义一个名为 calc_age 的函数,参数名为 birth_year,以英文冒号结尾
def calc_age(birth_year):
# 注意缩进,函数体中计算 2023 - birth_year 并赋值给变量 age
age = 2024 - birth_year
# 返回 age
return age
# 三次调用函数,传入不同参数,并将函数的返回值打印在屏幕上
print(calc_age(2001))
print(calc_age(1996))
print(calc_age(1988))
4、典型函数
现在的 circle()
函数,是一个典型的函数:既有 参数,又有 返回值。我们来分析一下它的结构:
它代表了一个函数的通用思路:
- 告诉 Python,要定义一个函数;
- 暗号名,即函数的名字是什么;
- (非必要)这个函数需要什么 参数;
- 处理过程是什么样的;
- (非必要)把什么样结果 返回 给外部。
有了这个通用思路,我们一定能写出功能明确的函数!
Python 中自带了很多函数,给我们提供了很多常用的功能,我们已经接触过了一些,比如 type()
、 input()
、str()
等,它们都是既有参数,又有返回值的函数。
print(type(5))
# 输出: <class 'int'>
5、函数的命名
函数的命名和变量的命名是一样的,由数字、字母、下划线组成,并且不可以用数字作为名称的开头。另外,名称本身要表达自己的功能,要简单易读,并且中间不能有空格。如果有多个单词,要用下划线 _
连接
下面这几个函数的命名方式是不推荐的,虽然符合 Python 语法,但是让人看得云里雾里。
yysy()
xswl()
aa_bb()
而下面这种命名方式是错误的,因为函数名中不能出现空格:
make juice()
下面的几个函数名是规范的:
total() # 让人一眼看出,功能是求总量
make_juice() # 表达功能,并且用了下划线分割单词。
在定义函数的过程中,新手程序员们最容易犯的错误有以下几点
第一行定义函数时,括号和冒号不小心写成了中文的。这会导致程序报错 (SyntaxError
):
# 我们故意把括号和冒号改成中文
def circle(r):
c = 2 * 3.14 * r
# 函数体最后一行加上 return 语句
return c
# 输出:
# SyntaxError: invalid character in identifier
# 语法错误:识别到无效字符
中文的括号和冒号会被识别为无效字符。所以我们要注意,不要犯这种低级错误哦
另一个,就是忘记在函数体前统一加缩进。这样也会导致程序报错 (IndentationError
):
def circle(r):
# 函数体故意不加缩进
c = 2 * 3.14 * r
return c
# 输出:
# IndentationError: expected an indented block
# 缩进错误:需要一个缩进代码块
在 Python 中,我们使用缩进来表示代码间的层级关系。因为函数体是函数里的一部分,所以函数体都必须要统一缩进(两个或四个空格)。
6、return语句的陷阱
return
语句有一个特别要注意的点,return
语句是函数执行结束的标记,运行完 return
语句,就会退出函数的执行,不管后面还有没有其它代码。所以我们一般都要把 return
语句放在最后。
def circle(r):
c = 2 * 3.14 * r
# 先打印计算结果
print('该圆的周长是' + str(c))
# 函数体最后一行加上 return 语句
return c
result = circle(2)
print(result)
这样写,我们就会得到两行打印结果:
1、该圆的周长是12.56
2、12.56
第一行的 “该圆的周长是12.56”,是由函数在执行时,内部的 print('该圆的周长是' + str(c))
打印出的结果。
第二行的 12.56,是变量 result
通过函数体最后一句 return c
, 获取了 c
的值,再由 print(result)
打印来的结果。
但如果我们将函数内部的 print('该圆的周长是' + str(c))
和 return c
调个位置,结果就不一样了。
def circle(r):
c = 2 * 3.14 * r
# 先返回结果 c
return c
# 最后打印计算结果
print('该圆的周长是' + str(c))
result = circle(2)
print(result)
此时我们只能得到一行结果:
12.56
是为什么?这就是我们在之前说的,运行完 return
语句,就会退出函数的执行啦。return c
运行完,circle(2)
就自动认为运行结束,后面的 print('该圆的周长是' + str(c))
就没有机会运行了!
7、练习题:
1、下列代码的运行结果是?
def light():
print('红灯')
print('绿灯')
print('黄灯')
light()
A、红灯、绿灯、黄灯
B、红灯、绿灯
C、黄灯、红灯、绿灯
D、黄灯
正确答案是:C
print('黄灯')
没有缩进,所以不属于 light()
函数。因此先执行 print('黄灯')
,再执行 light()
函数。
2、下列关于 Python 中函数定义的代码是否正确?
def say_hello()
print('Hello')
A、正确
B、错误
正确答案:B
括号后少了英文冒号,正确的写法如下:
def say_hello():
print('Hello')
3、下列代码的运行结果是?
def func_1():
print('猪猪')
def func_2():
name = '羊羊'
func_1()
func_2()
func_1()
A、猪猪、养养
B、猪猪、猪猪
C、养养、养养
D、养养、猪猪
正确答案:B
函数 func_1()
打印 '猪猪'
,而函数 func_2()
在内部定义了一个变量 name
,只是为它赋值,并没有打印。