ʕ • ᴥ • ʔ
づ♡ど
🎉 欢迎点赞支持🎉
个人主页:励志不掉头发的内向程序员;
专栏主页:python学习专栏;
前言
一、函数是什么
编程中的函数和数学中的函数有一定的相似之处。
我们从初中开始就已经学习了各种各样的函数了,就比如一次函数、二次函数、三角函数、一元二次函数等等。
而数学上的函数,相当于是一种 “映射关系”。把我们的参数通过一系列的数据变换后生成一个结果。
编程中的函数,是一段可以被重复使用的代码片段。
在我们的编程过程中,一个软件在很多地方可能会遇见类似的功能,此时我们不可能把一个代码重复写 N 遍。可能会有人会使用 CV 大法,但是我们可能这些相似的地方只是逻辑相同,但是数据不同,那我们还是需要去修改我们的数据。
我们复制代码必须要非常仔细的进行细节调整,尤其是数据不同的情况下。而且一旦复制过的代码需要调整,那复制了几份就得调整几次,但是我们一般搞不清楚这个代码究竟被复制了几份了。因此我们尽量还是不要复制代码,尽量还是做好代码 “重用”,也就是我们先写好一份代码放在一个地方,等我们要使用时就去调用那个地方的代码,这才是我们希望的代码。而我们的函数就是为了实现这样的功能而存在的。
我们来尝试一下之前学过的代码,求 1-100 的和。
# 1. 求 1-100 的和
theSum = 0
for i in range(1, 101):
theSum += i
print(theSum)
不是很难,此时我们再来看看求 300-400 的和。
# 2. 求 300-400 的和
theSum = 0
for i in range(300, 401):
theSum += i
print(theSum)
我们再来求求 1-1000 的和试试。
# 3. 求 1-1000 的和
theSum = 0
for i in range(1, 1001):
theSum += i
print(theSum)
我们可以发现,我们确实都能完成这些计算,而且也很容易和方便。
但是这不就是我们刚才所说的把一份代码重复了很多遍吗。这些代码的形式都是一样的,只是计算的数据范围不一样,其他的逻辑都是一样的。像上述的情况,我们就可以通过函数的形式来简化我们的编写,来达到一个复用代码的效果。
那我们就尝试用函数的方式来解决这个问题。
# 定义一个求和函数
def calcSum(beg, end):
theSum = 0
for i in range(beg, end + 1):
theSum += i
print(theSum)
这就是定义的函数,这个函数的功能就是输出从 beg-end 相加的总和。我们可以发现我们刚才具体的值 1-100、300-400、1-1000 都被一个抽象的值所代替了。当我们想要调用这个函数时,我们只需要传输具体的值去代替抽象的值则可实现我们想要的运算。
# 调用函数
# 求 1-100 的和
calcSum(1, 100)
# 求 300-400 的和
calcSum(300, 400)
#求 1-1000 的和
calcSum(1, 1000)
我们把 1-100、300-400、1-1000 分别代替掉 beg、end。就达成了我们上面重复写的效果。
这就是我们函数的作用和意义。如果我们未来有一天想要对我们的这串逻辑进行修改,我们直接修改函数即可完成全部的修改。
二、语法格式
创建函数/定义函数(分配任务)
def 函数名( 形参列表 ):
函数体
return 返回值
使用函数/调用函数(完成任务)
函数名( 实参列表 ) # 不考虑返回值
返回值 = 函数名( 实参列表 ) # 考虑返回值
注:函数的定义并不会执行函数体的内容,必须要调用才会执行,调用几次就会执行几次。
函数定义的关键字是 def,是 define(定义)的缩写。def 后面紧跟着的就是函数名,和我的变量名是类似的作用,命名规则和变量的命名规则是一样的。
函数名后面有个 ( ),这个 ( ) 中里面要插入的是形参列表,在这个形参列表中可以有多个形参。多个形参之间使用逗号分隔。
冒号过后就是函数体了,也就是这个函数具体要做的事情,就是由这个函数体来进行表示。函数体部分要带有一级缩进,带有缩进的代码才是函数内部的语句。
有的函数还带有一个特殊的语句,那就是 return 语句。当我们函数运行到 return 语句时就意味着我们的函数执行完毕了。而我们 return 后面的值就是函数的返回值。这个 return 语句也不是必须的,它可以有也可以没有,视具体情况而定。
当我们函数定义好之后就可以去完成我们的任务了。函数定义完了并不意味着立刻就开始使用,就像老师布置作业并不意味着你就立刻开始写作业一样。一直要到函数调用时,函数才会开始使用。函数的调用就只需要函数名加上 (实参列表) 即可,我们实参列表中也可以有多个实参。多个实参之间也要使用逗号分隔。当然,我们实参的个数要和我们形参的个数是匹配的。形参有几个参数,我们的实参就得有几个参数,而且实参和形参的参数的位置是一一匹配的。这样就方便我们实参一一匹配的传输给我们形参了。
当然,我们函数还有一种有 return 语句的情况。这种情况我们就得使用
返回值 = 函数名( 实参列表 )。
如果我们的函数没有返回值,或者它的返回值我们不关心,就没有必要使用这种方法。
# 定义一个函数
# 如果只是定义而不去调用,我们函数体里面的代码就不会执行
def test():
print("hello")
print("hello")
# 函数调用才会真正执行函数体里面的代码
# 函数经过一次定义后,可以调用多次
# 函数的调用
test()
我们也可以调用多次。
# 函数的调用
test()
test()
test()
注意:Python 中要求,函数定义写在前面,函数调用写在后面。
test()
def test():
print("hello")
print("hello")
不能这样写。
编译器会不认识。
三、函数参数
在函数定义的时候,可以在 ( ) 中指定 “形式参数”(简称形参),然后在调用的时候,由调用者把 “实际参数”(简称实参)传递进去。
这样就可以做到一份函数,针对不同的数据进行计算处理。
我举个例子让你们来理解一下什么是实参,什么是形参。
有一家工厂,有一个很神奇的生产线,我们只要投入 3 个石头和 2 个木棍就可以生成一个镐子。于是工人们就放了 3 个铁块和 2 个木棍就生成了一个铁镐。
此时我们提供不同的原材料就是我们的实参,也就是实际参数。而我们需要的石头和木棒就是我们形参,也就是形式参数。我们的原材料(实际参数)通过我们的传送带传送给工作台的形参,然后再在工作台(函数体)上制作,最后返回我们的成品(返回值)。我们传递不同的实参,我们的形参就给不同的实参所替换,最终得到的返回值也就不同了。
我们来看看上面的代码。
def calcSum(beg, end):
theSum = 0
for i in range(beg, end + 1):
theSum += i
print(theSum)
# 调用函数
# 求 1-100 的和
calcSum(1, 100)
# 求 300-400 的和
calcSum(300, 400)
#求 1-1000 的和
calcSum(1, 1000)
我们可以看到,我们的形参就是 beg,end。而我们求 1-100 的和的实参是 1,100.我们拿我们 1,100 去替换掉 beg,end 就可以得到 1-100 的和了。剩下的也是一样的。本质就是在函数调用时,我们的实参分别的按照次序的赋值给上述形参。
我们在传实参时一定得注意,我们实参的个数是要和形参的个数匹配的。
def test(a, b, c):
print(a, b, c)
test(10)
像我们这样,形参有多个,但是实参就只要一个是不行的。
它这里就直接报错了。错误提示是这里缺少两个关键位置b和c。
实参多写也是不行的。
def test(a, b, c):
print(a, b, c)
test(10, 20, 30, 40)
同时我们传参的位置是一一对应的,第一个实参就对应第一个形参,以此类推。
def test(a, b, c):
print(a, b, c)
test(10, 20, 30)
def test(a, b, c):
print(a, b, c)
test(20, 30, 10, )
Python 中只是要求个数,对类型没有要求,因为 Python 中有动态类型。当然也不是说随便传入啥类型都行,只要保证传入的参数类型,在函数体里面能够支持对应的运算操作即可。
四、函数返回值
函数的参数可以视作是函数的 “输入”,则函数的返回值,就可以视为是函数的 “输出”。
此处的 “输入”,“输出”是更广义的输入输出,不是单纯的指通过控制台的输入和输出。
我们应该还记得这张图,我们的原材料就是输入(参数),而加工出来的成品就是输出(返回值)。
我们再来看看我们之前的代码。
# 求 beg,end 这个范围的整数之和
def calcSum(beg, end):
theSum = 0
for i in range(beg, end + 1):
theSum += i
print(theSum)
calcSum(1, 100)
我们可以很顺利的打印 1-100 的总和。
但是像这样的一串代码,我们可以进行等价的转换。
# 求 beg,end 这个范围的整数之和
def calcSum(beg, end):
theSum = 0
for i in range(beg, end + 1):
theSum += i
return theSum
result = calcSum(1, 100)
print(result)
我们可以把我们的 theSum 做返回值返回回来,然后再用 result 变量保存起来再输出。这样和我们原来的效果是相同的。
这个代码和之前的区别在于,原来的那个代码既负责运算,又负责打印。而这个函数就只负责运算,打印操作就交给函数外面进行了。
我们一般在实际开发中都是以第二种方法为主,很少使用第一种方法。因为我们 Python 中有一个通用的编程原则:一个函数只做一件事,第一个版本既做了计算,又做了打印。
我们的 return 语句还有很多用法:
1、一个函数中可以有多个 return 语句。
def test():
return 1
return 2
这种情况不算是有多个 return 语句,因为我们的函数在运行到第一个 return 语句是就立即返回了,所以根本运行不到第二个 return 语句。
我们多个 return 语句一般都是搭配分支语句 /循环语句来使用的。
# 写一个判断奇数还是偶数的函数
def isOdd(num):
if num % 2 == 0:
return False
else:
return True
我们通过这样的代码就实现了我们奇数还是偶数的判定,同时还包含了两个 return 语句,具体运行哪个 return 语句还不确定,具体看是奇数还是偶数。
print(isOdd(10))
print(isOdd(19))
2、执行到 return 语句,函数就会立即执行结束,回到调用位置。
我们的函数只要读到了 return 就会立刻结束,就比如我们刚才的 return 1 后又加了一个 return,我们的编译器的报错就是永远也不会到达 return 2。就是因为程序读到 return 1 后就直接返回了,没有继续往下读的可能。
我们判段奇数还是偶数的代码还可以这样写。
def isOdd(num):
if num % 2 == 0:
return False
return True
这个和刚才的代码是没有区别的,原因也是我们函数在满足 if 条件时读到 return 后就直接返回了,没有往下读的可能。只有不满足才有往下读的可能。
3、一个函数是可以一次返回多个返回值的,使用 , 来分割多个返回值。
# 写一个函数返回平面上的一个点
# 横坐标,纵坐标
def getPoint():
x = 10
y = 20
return x, y
a, b = getPoint()
print(a, b)
4、如果只想关注其中的部分返回值,可以使用 _ 来忽略不想要的返回值。
我们接着来看我们上一个代码。
# 写一个函数返回平面上的一个点
# 横坐标,纵坐标
def getPoint():
x = 10
y = 20
return x, y
此时我们不想关注我们的 x,只想关注我们的 y,可以在我们接收的位置用 _ 来把 x 位置给占了。
_, b = getPoint()
print(b)
此时我们就接收不到我们的 x 了。
总结
以上便是我们函数的部分内容,干货满满,如果学习了其他语言的小伙伴可能可以看出 Python 和我们学的语言确实还是有所区别的,部分改进还是挺好的。我们大家得认真学习,下一章节接着讲解我们函数剩余内容,大家下期再见。
🎇坚持到这里已经很厉害啦,辛苦啦🎇
ʕ • ᴥ • ʔ
づ♡ど