原创:公众号 数据说话
函数介绍
学习目标:
-
快速体验一下函数的使用
-
了解函数的作用。
函数:是组织好的,可重复使用的,用来实现特定功能的代码段。如果这句话不好理解的话,我们可以看下面的例子:
name = "itheima"
length = len(name)
print(length)
#结果为:7
为什么随时都可以使用 len()统计长度?因为,len()是Python内置的函数:
• 是提前写好的
• 可以重复使用
• 实现统计长度这一特定功能的代码段
我们使用过的:input()、print()、str()、int()等都是Python的内置函数。
接下来让我们来做一个实际的小案例,让我们去体验一下函数的使用,那么案例的需求其实也是非常简单的,我们不使用 Python 内置提供的函数 len,我们要自己去开发功能,去完成字符串长度的计算。
"""
演示:快速体验函数的开发及应用
"""
# 需求,统计字符串的长度,不使用内置函数len()
str1 ="itheima"
str2 = "itcast"
str3 ="python"
# 定义一个计数的变量
count =0
for i in str1:
count += 1
print(f"字符串{str1}的长度是: {count}")
count = 0
for i in str2:
count += 1
print(f"字符串{str2}的长度是: {count}")
count = 0
for i in str3:
count += 1
print(f"字符串{str3}的长度是: {count}")
我们是否发现这些代码有点重复?它们有什么不同之处?唯一不同的是被统计的字符串,除此之外,这些代码完全相同。这种完全相同的代码会让人觉得浪费,对吧?这样的写法非常低效。那么该如何提高效率呢?我们可以使用函数来优化这个过程,下面演示一下。
好的,现在我来简单地定义一个函数。我们给它起名叫做 "mylen",这个函数的功能是计算数据的长度。现在我写下这个代码,可能有些同学看不懂,但没关系,我们只需要看结果就可以了。
# 可以使用函数,来优化这个过程
def my_len(data):
count =0
for i in data:
count += 1
print(f"字符串{data}的长度是{count}")
my_len(str1)
my_len(str2)
my_len(str3)
好的,这样我们就简单地定义了一个函数。当我们定义好函数之后,就可以去使用它了。使用方法也很简单,只需要调用函数 "mylen",并将需要计算长度的字符串放在函数中即可。
运行,可以看到输出结果是
字符串itheima的长度是7
字符串itcast的长度是6
字符串python的长度是6
和第一次的运行结果是一样的,通过这段代码,你可以比较一下它们之间是否有什么不同。
区别在于,我们的函数好像封装了这个重复的工作。在这段重复的代码中,唯一的变量是被统计的字符串。在使用它时,我们只需要将需要统计长度的字符串作为参数传递进去即可。它可以根据你提供的内容动态计算长度。
因此,通过这段简单的代码,同学们可以发现,使用函数可以避免重复的编写代码。同时,我们编写的名为 "mylen" 的函数可以重复使用。再来看看我们对函数的简单定义:
第一个是已组织好的,第二个是可重复使用的,第三个是针对特定功能的。
现在再看看我们编写的这个函数,首先它是否满足已组织好的?这意味着我提前编写了它的功能逻辑。
其次,它是否可重复使用?没有问题,我们使用 "mylen" 很多次了,对吧?
第三点是针对特定功能的。您看看我们编写的 "mylen" 函数,它的功能是什么?它计算字符串的长度。因此,我们编写的这个函数完全符合这三个特点,这是一个典型的函数。
函数的定义
在一小节,我们对函数有了一个基础的体验,那么现在呢我们来学习函数的定义啦,本小节的目标也非常明确,我们要在本小节,完成函数的基础定义语法。
函数的定义:
首先我们来看一下函数的定义语法,它的语法是比较简单的。我们可以用 def 这个关键字来标识,表示我们要写一个函数。然后在空格后面我们写上函数名,可以在小括号里面写传入的参数。最后通过一个冒号作为当前行的结尾。这个冒号也是我们经常会看到的,比如在 for 循环、while 循环、if 判断中都会出现。当我们写完冒号之后,下面的行都会带有空格缩进。
接下来我们就可以在下面换行去写函数体,函数体指的是函数要做的事情。 完成函数体后,最后我们可以通过一个 return 来返回一个值。
def 函数名(传入参数):
函数体
return返回值
所以一个函数的组成就是关键字 def、函数名、传入参数、函数体和返回值这 5 部分。
在我们当前的基础定义语法中,我们暂时不讨论传入参数以及返回值。这两者都是可以省略的,我们在后面的章节再去详细讨论它。所以到目前为止,我们一个基础的函数定义只需要写上 def 关键字,给上函数名,写上函数体就可以了。所以我们只需要有这 3 个要素就可以了。
函数的调用:
函数名(参数)
注意:
①参数如不需要,可以省略(后续章节讲解)
②返回值如不需要,可以省略(后续章节讲解)
③函数必须先定义后使用 到目前来看,我们一个基础的函数定义,只需要写上def关键字,给上函数名,写上函数体就可以了,所以我们只需要有这3个要素就OK了,举一个例子:
# 定义一个函数,输出相关信息
def say_hi():
print("Hi 我是黑马程序员,学Python来黑马")
在定义完函数之后,为了让它开始工作,必须进行调用。这就好比你拥有了一个工具,如果想要使用它,就必须给它通电。当我们调用一个函数时,就相当于给这个工具通电,让它真正开始工作。因此,我们需要调用函数,以便让定义的函数执行任务。
接下来,让我们来看一下第二种函数的语法应该如何书写。这个过程很简单,只需要写出函数名,然后在小括号中写入参数即可。不过需要注意的是,当我们在定义函数时省略了参数时,在调用时也可以不传递参数,只需要写出函数名,并在小括号中留空即可。
# 调用函数,让定义的函数开始工作
say_hi()
这样一来,结果就输出了:
Hi 我是黑马程序员,学Python来黑马
注意事项:
-
参数不需要,可以省略
-
返回值不需要,可以省略
函数的参数
上一小节,我们完成了函数的基础定义,并且我们说到,函数的定义中可以使用传入参数,但是我们并没有去解析它,好那么在本小节我们就来讲解一下,关于函数的参数的使用。
学习目标:
-
掌握如何使用传入参数
函数的传入参数
传入参数的功能是:在函数进行计算的时候,接受外部(调用时)提供的数据,那这是具体怎么用呢,我们首先来看一个案例,有如下代码,完成了2个数字相加的功能:
def add():
result = 1 + 2
print(f"1+2的结果是:{result}")
add()
函数的功能非常局限,只能计算1 + 2。 有没有可能实现:每一次使用函数,去计算用户指定的2个数字,而非每次都是1 + 2呢? 可以的,使用函数的传入参数功能,即可实现。
函数的传入参数 - 传参定义
首先基于函数的定义语法,可以看到在小括号里面是不是有传入参数的语法的位置。那所以当我们定义参数的时候,就可以在这里写上参数定义了。
def 函数名(传入参数):
函数体
return 返回值
比如刚刚的两数相加的函数,我们在括号里面可以写上一个x,y,这就表明我接收两个参数的传入,那当我计算的时候怎么写呢,我们就不再写1+2了,我们直接写x和y进行相加,然后,得到具体的结果输出出去就可以了,那当我们以这样的语法去写的时候,每次调用函数的时候,就可以去手动的指定x是几,y是几,那么每一次的计算,都是我们用户指定谁和谁进行相加了,这样是不是就非常的完美了。
可以有如下函数定义:
def add(x,y):
result =x + y
print(f"{x}+{y}的结果是:{result}")
实现了每次计算的是x + y,而非固定的1 + 2 的值,可以在调用函数的时候指定。
# 调用函数,传入被计算的2个数字
add(5, 6)
结果是11
函数的传入参数 - 语法解析
语法解析:
#定义函数
def add(x,y):
result= x + y
print(f"{x}+{y}的结果是:{result}")
#调用函数
add(5,6)
-
函数定义中,提供的x和y,称之为:形式参数(形参),表示函数声明将要使用2个参数
-
参数之间使用逗号进行分隔
-
函数调用中,提供的5和6,称之为:实际参数(实参),表示函数执行时真正使用的参数值
-
传入的时候,按照顺序传入数据,使用逗号分隔
那么解析完之后,我们再来看一下我们当前定义的函数。它是一个两个参数的函数,那么我们的函数只能接收两个传入参数吗?显然不是。通过前面的学习,我们知道函数可以不使用参数。那么就通过刚刚的代码,我们发现函数也可以使用参数。我们使用了2个,但实际上函数可以使用任意n个参数。你可以给1个,可以给2个,可以给3个,也可以给10个。你给几个都可以。
传入参数的数量是不受限制的。
-
可以不使用参数
-
也可以仅使用任意N个参数
可以把刚刚的代码改成3个参数:
# 定义3数相加的函数,通过参数接收被计算的2个数字
def add(x, y, z):
result = x + y + z
print(f"{x} + {y} + {z}的计算结果是:{result}")
# 调用函数,传入被计算的3个数字
add(5, 6, 7)
是不是也计算出来了,那所以我们的传入参数的数量,它是不受限制的。
函数的返回值
函数返回值这1小节,我们主要分成两部分进行讲解,首先让我们来学习第一部分,函数返回值的定义语法。 学习目标,
-
能够掌握返回值的作用
-
返回值的定义语法
什么是返回值
生活中的返回值:
举个生活中的小例子,比如我让小明去买三瓶可乐。你可以把小明看作一个函数,而让他买三瓶可乐相当于给函数传递参数。一旦传递了参数,小明这个函数就开始工作了,他会回应说:“我去买可乐了”。等他买完可乐之后,他会把可乐交给我,这个可乐就相当于是函数的返回值。
因此,生活中的例子很简单,就是我让你做一件事情,你做完之后给我一个结果。在程序中,我们也需要关注事情的结果!
对于代码程序中的返回值:
我们来看一下代码中的反馈。定义了一个简单的两数相加的函数。这个函数的功能很简单,让a和b相加,将结果存入变量result中。然后我们在代码中使用了一个叫做return的关键字。它的功能是将return后面的值返回出去。
返回出去的意思是什么呢?我们来看下面这段代码。当我们调用函数add时,你会发现它的结果被一个叫做result的变量接收了。当我们使用print将这个变量输出时,结果是3。这不就代表了1和2相加的结果吗?这个return语句已经将它的返回值返回出去了,被result接收了。
def add(a,b):
result = a +b
return result
result = add(1,2)
print(result)
定义两数相加的函数功能。完成功能后,会将相加的结果返回给函数调用者,变量r接收到了函数的执行结果。
综上所述:
所谓“返回值”,就是程序中函数完成事情后,最后给调用者的结果。
info 函数执行完返回值,后面的所有代码都不会再执行。因此,函数体只要遇到return关键字,就会立刻结束。 如果你在retern result 后加一句:print("我完事了")根本不会执行。因此,我们需要注意这个细节。
返回值的语法:
语法格式如下:
def 函数(参数...):
函数体
return 返回值
变量 = 函数(参数)
如上,变量就能接收到函数的返回值去实践一下吧:定义一个函数,完成两数相加的功能,并返回结果 语法就是:通过return关键字,就能向调用者返回数据。
None类型
思考:如果函数没有使用return语句返回数据,那么函数有返回值吗?
实际上是:有的。
Python中有一个特殊的字面量:None,其类型是: 无返回值的函数,实际上就是返回了:None这个字面量
None表示:空的、无实际意义的意思
函数返回的None,就表示,这个函数没有返回什么有意义的内容。
也就是返回了空的意思。
也就是说我们的函数不管你写不写 return 语句,本质上都是有返回值的,你不写它就是返回none。
那所以当我们去写函数的时候去调用它,比如下面的代码,这个函数没有去声明我们的return语句,但本质上你可以用一个变量去接收它的返回值,并且打印它的内容和打印它的类型,你会发现结果是 None 类型就是我们的 None type。又或者我们所说这个 None 也可以通过return,你可以手动的主动返回None,也都是可以的。
演示:
def say_hello():
print("Hello...")
#使用变量接收say_he1lo函数的返回值
result = say_hello()
# 打印返回值
print(result) # 结果None
# 打印返回值类型
print(type(result)) # 结果<class'NoneType'>
None可以主动使用return返回,效果等同于不写return语句:
def say_hello():
print("Hello...")
return None
#使用变量接收say_hello函数的返回值
result = say_hello() # 打印返回值
print(result) # 结果None
None类型的应用场景
None作为一个特殊的字面量,用于表示:空、无意义,其有非常多的应用场景。
-
用在函数无返回值上
-
用在if判断上
-
在if判断中,None等同于False
-
一般用于在函数中主动返回None,配合if判断做相关处理
-
用于声明无内容的变量上
-
定义变量,但暂时不需要变量有具体值,可以用None来代替
#暂不赋予变量具体值
name = None
我们现在有一个简单的函数,它的功能很简单,检查你的年龄,然后判断你的年龄是否大于18岁,成年就可以了。如果你传入的年龄大于18岁,我们就返回一个有价值的叫做SUCCESS的值,表示成功的意思。但是如果你的年龄没有满足大于18岁,我们就返回None。对于这种函数,我们可以在后面调用它,比如说check_age函数调用它之后,如果我传一个16岁,那么它肯定返回None,然后得到一个result结果。那么我们可以判断这个result是不是None,我们可以这样写if result == None,但是这样有点啰嗦。我们可以直接写if not result,这样就可以判断resource是不是None值了。
def check_age(age):
if age >18:
return "SUCCESS"
return None
result = check_age(5)
if not result:
print("未成年,不可进入")
好的,你进来之后我可以简单地说一下。我们这个网吧是不允许未成年人进入的。因此,我们需要使用一个简单的函数来返回一个值,然后再用 if 语句进行判断。由于我们的返回值是 None,它表示 False,我们可以通过 if 语句来判断返回值,然后执行相应的操作。
函数的说明文档
学习目标
-
掌握通过注释对函数进行解释说明
函数是纯代码语言,想要理解其含义,就需要一行行的去阅读理解代码,效率比较低。
我们可以给函数添加说明文档,辅助理解函数的作用。
语法如下:
def func(x,y):
"""
函数说明
:param x:形参x的说明
:param y:形参y的说明
:return:返回值的说明
"""
函数体
return返回值
在上面的代码中,我们在函数定义和函数体之间添加了一个多行注释,这就是函数的说明文档。虽然本质上你可以自由书写多行注释,但是如果想要规范一些,我们遵循一些语法格式会更有用。
在这个多行注释中,我们可以对函数进行总体说明,用冒号 param 对参数 x 进行说明,用冒号 param 对形参 y 进行说明,用冒号 return 对返回值进行说明。通过这种格式,我们不仅可以对函数整体进行解释,还可以对其参数和返回值进行相应的说明。
注意:内容应写在函数体之前
下面通过代码来实际演练一下:
"""
演示对函数进行文档说明
"""
# 定义函数,进行文档说明
def add(x, y):
"""
add函数可以接收2个参数,进行2数相加的功能
:param x: 形参x表示相加的其中一个数字
:param y: 形参y表示相加的另一个数字
:return: 返回值是2数相加的结果
"""
result = x + y
print(f"2数相加的结果是:{result}")
return result
add(5, 6)
在PyCharm中查看函数说明文档
在PyCharm编写代码时,可以通过鼠标悬停,查看调用函数的说明文档, 这个作用非常的有用。以后当我们写函数,只要你写的函数,我们都建议你把说明文档都给它补齐了,这样才是一个比较规范的函数定义。
函数的嵌套调用
学习目标
-
掌握函数的嵌套调用
-
理解嵌套调用的执行流程
什么是函数的嵌套
所谓函数嵌套调用指的是一个函数里面又调用了另外一个函数, 那当你发生这种行为,我们就把它叫做函数的嵌套调用。比如下面的代码,我们定义了两个函数,分别是 fun_b 和 fun_a, 在fun_a 里面,它调用了fun_b,然后我们又调用了函数fun_a,让它去执行。当我执行fun_a 函数的时候,你来看它的执行结果输出了 1、2、3。所以,在fun_a 里面,我们先输出了 1,然后又去调用了 b,将 2 输出了,最后又输出了 3。这就是函数的嵌套调用的一个形式。
def func_b():
print("---2---")
def func_a():
print("---1---")
func_b()
print("---3---")
# 调用函数func a
func_a()
执行效果:
---1---
---2---
---3---
那么嵌套调动的流程非常简单,我们也简单的分析了一下。 让我们进如下一小节的学习。
变量的作用域
学习目标
-
知道什么是局部变量
-
知道什么是全局变量
局部变量
变量作用域指的是变量的作用范围(变量在哪里可用,在哪里不可用)主要分为两类:局部变量和全局变量 所谓局部变量是定义在函数体内部的变量,即只在函数体内部生效
def testA():
num = 100
print(num)
testA() # 100
print(num) # 报错:name'num'is not defined
#
变量a是定义在testA函数内部的变量,在函数外部访问则立即报错, 它会提示你 name number is not defined。他说这个 number 变量并没有被定义,那这就是局部变量。
局部变量的作用:在函数体内部,临时保存数据,即当函数调用完成后,则销毁局部变量
全局变量
所谓全局变量,指的是在函数体内、外都能生效的变量
思考:如果有一个数据,在函数A和函数B中都要使用,该怎么办?答:将这个数据存储在一个全局变量里面
那么,如何使用全局变量呢?其实很简单,只需将变量定义在函数外部即可。只要不是在函数内部,变量在函数中和函数外部都可以正常使用。
如下方代码所示,test_a和test_b都可以调用num。
#定义全局变量a
num = 200
def test_a():
print(f"test_a: {num}")
def test_b():
print(f"test_b: {num}")
test_a()
test_b()
print(num)
global关键字
好,了解了局部变量和全局变量之后,我们再来看下一个内容,叫做 global 关键字。现在我们有一个需求,想在函数内部修改全局变量的值,比如说把它从100改成200。这种修改操作会成功吗?让我们来试一下。在下面的代码中,写一个函数内部去修改全局变量,比如在 test_b 中把 number 改成500。执行顺序是先调用 test a,再调用 test b,最后输出num。在最后输出这个 num 的时候,已经将 num 修改成了500。让我们来看看最后这个输出的 num 到底是200还是500。好,现在我们来运行一下。
# 在函数内修改全局变量
num = 200
def test_a():
print(f"test_a: {num}")
def test_b():
num = 500 # 局部变量
print(f"test_b: {num}")
test_a()
test_b()
print(num)
运行结果是:
test_a: 200
test_b: 500
200
你会发现 test_a 的值是 200,没有问题。那 test_b 呢?它输出的数字已经被成功修改为 500 了?这也没问题,但是在函数外面的那个数字仍然是 200,这说明我们这一步修改好像对它没有生效。这是为什么呢?因为我们在函数内部定义的那个数字实际上是一个局部变量。也就是说,我们在函数内部定义了一个叫做 num 的变量,并把它的值设置为 500,这个 num 在我们函数内部正常使用,但是它和函数外面的那个 num 没有任何关系。相当于我们新定义了一个变量,只在函数内部使用。所以,虽然你在内部能够获取到 500,但是在外部,这个数字是 200 还是 200,它们之间是没有任何联系的。
如何修改程序?只要加上一个global关键字即可:
☆ 使用 global关键字可以在函数内部声明变量为全局变量,如下所示
# global关键字,在函数内声明变量为全局变量
num = 200
def test_a():
print(f"test_a: {num}")
def test_b():
global num # 设置内部定义的变量为全局变量
num = 500
print(f"test_b: {num}")
test_a()
test_b()
print(num)
输出结果:
test_a: 200
test_b: 500
500
最后这个 num 变成 500 输出,那这是 global 关键字的作用,它可以让我们在函数内定义的变量成为全局变量。
综合案例
来看一个案例:黑马ATM,实现以下的效果: 主菜单效果
-
查询余额效果
存、取款效果
思路:
-
定义一个全局变量:money,用来记录银行卡余额(默认5000000)
-
定义一个全局变量:name,用来记录客户姓名(启动程序时输入)
-
定义如下的函数:
-
查询余额函数
-
存款函数
-
取款函数
-
主菜单函数
要求:
-
程序启动后要求输入客户姓名
-
查询余额、存款、取款后都会返回主菜单
-
存款、取款后,都应显示一下当前余额
-
客户选择退出或输入错误,程序会退出,否则一直运行
参考代码:
"""
演示函数综合案例开发
"""
# 定义全局变量money name
money = 5000000
name = None
# 要求客户输入姓名
name = input("请输入您的姓名:")
# 定义查询函数
def query(show_header):
if show_header:
print("-------------查询余额------------")
print(f"{name},您好,您的余额剩余:{money}元")
# 定义存款函数
def saving(num):
global money # money在函数内部定义为全局变量
money += num
print("-------------存款------------")
print(f"{name},您好,您存款{num}元成功。")
# 调用query函数查询余额
query(False)
# 定义取款函数
def get_money(num):
global money
money -= num
print("-------------取款------------")
print(f"{name},您好,您取款{num}元成功。")
# 调用query函数查询余额
query(False)
# 定义主菜单函数
def main():
print("-------------主菜单------------")
print(f"{name},您好,欢迎来到黑马银行ATM。请选择操作:")
print("查询余额\t[输入1]")
print("存款\t\t[输入2]")
print("取款\t\t[输入3]") # 通过\t制表符对齐输出
print("退出\t\t[输入4]")
return input("请输入您的选择:")
# 设置无限循环,确保程序不退出
while True:
keyboard_input = main()
if keyboard_input == "1":
query(True)
continue # 通过continue继续下一次循环,一进来就是回到了主菜单
elif keyboard_input == "2":
num = int(input("您想要存多少钱?请输入:"))
saving(num)
continue
elif keyboard_input == "3":
num = int(input("您想要取多少钱?请输入:"))
get_money(num)
continue
else:
print("程序退出啦")
break # 通过break退出循环
代码较长,可以自己先练习写一下,并拆解参考里的代码。