【爆肝更新】Python基础教程:第五章_Python函数

原创:公众号 数据说话

【爆肝更新】Python基础教程:第五章_Python函数

函数介绍

学习目标:

  • 快速体验一下函数的使用

  • 了解函数的作用。

函数:是组织好的,可重复使用的,用来实现特定功能的代码段。如果这句话不好理解的话,我们可以看下面的例子:

 
 
 
 

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退出循环

代码较长,可以自己先练习写一下,并拆解参考里的代码。

猜你喜欢

转载自blog.csdn.net/Blue92120/article/details/130607219