搬砖的也能玩Python——基础篇
6-函数
回顾
通过前面五篇文章,我们已经掌握了Python的数据类型以及条件循环语句,本篇文章开始,我们将了解另外两个非常重要的概念:函数和类。
我们先从函数开始。
一、回忆基础篇2
说到函数,我们在基础篇2最开始的引子中简单的说了一下,不知大家是否还有印象。当时提到所谓的函数,其实就是一种对数据的操作,比如print("Hello, World!"),就是对"Hello, World!"这个数据进行了输出到控制台的操作。
当时我们主要是说了如何使用函数,本篇文章我们就来说一下如何去定义一个函数。
二、函数概念
在讲函数的概念之前,我们先来思考下面一个问题。
思考
在上一篇文章中,我们利用循环计算了1+2+...+20000,但如果我们想计算很多次求和,也就是1+2+...+n,每次n的值都不一样,应该怎么办?
解析
按照上一篇文章的内容,我们只能针对每一个n,都要重新写一遍循环语句,这样我们就写了非常多的重复代码,效率也更慢。因此,我们就引出函数这个概念,来解决这个问题。
所谓的函数,就是一个代码段,这个代码段是可重复利用的,并且用来实现某些功能的代码段。当我们需要多次执行同一项任务的时候,就无需反复编写同样的代码,只需要调用函数即可。
我们先来看一个最简单的函数,就拿"Hello, World!"来看吧。
在上图中,我们定义了一个hello函数,函数里面写了一个print()方法。通过hello方法后面加上括号,我们使用了这个hello函数,我们来看一下结果。
这样就是一个最简单的函数。
三、函数定义
我们来具体看一下一个函数应该如何定义:
def 函数名(参数):
函数体(函数代码块)
return 返回值
定义一个函数主要由以下6部分组成:
def关键字(必须)
函数名(必须)
参数(非必须)
函数体(必须)
return关键字(非必须)
返回值(非必须)
注意
函数跟条件语句、循环语句一样,通过缩进的规则来判断函数体,所以在定义函数的时候,一定不要忘记冒号(:),并且函数体要有一个Tab的缩进。由于return语句也是函数的一部分,所以也要有一个Tab的缩进。
通过函数的结构我们看到,def关键字、函数名、函数体是必须要有的,也就是上面的hello函数,函数名是hello,函数体是print()语句。
接下来我们具体看一下参数和返回值。
四、函数中的参数
函数中的参数,相当于向函数传递信息,然后函数体来处理传递进来的信息,一共有两种类型的参数:
形参:函数定义中的参数,代表一类数据
实参:使用函数时传入的参数,代表具体的数据
对于初学者来说,可能参数这一块有些难理解,我们来进行一个类比。
参数类比
在数学中也有函数这个概念比如f(x)=ax²+bx+c,在这里面x就是一个参数,f()就是一个函数,ax²+bx+c就是函数体的具体内容,当x=1时,f(1)=a+b+c。
放到Python中,x就是我们的形参,1就是我们的实参。
我们回到最开始求和的问题,有的参数的概念之后,我们就可以很好的解决重复编码的问题了,来看下面的代码。
从上图中看到,我们定义了“求和”函数,并且定义了一个参数n,函数体就是通过循环计算了1+2+...+n。在我们调用函数的时候,我们传入了具体n的值20000和100,最终得到我们的求和结果。这就是一个最简单的参数应用,本篇文章的最后我们会再详细学习几种不同的参数种类。
五、返回值
我们把上面的求和函数改一下,把函数体中的print(s)注释掉,我们来看一下结果是什么。
很明显,不会得到任何结果,因为在函数中,我们最终的结果存在了s变量中,之前有print()方法可以直接把s输出来,但注释掉之后,我们就没有办法得到s的值。
那么我们想得到这个值,并且在后面的代码中可以使用它的话,应该如何做?这就是返回值所要实现的内容。通过return关键字,将s变量最终的值从函数中传递出来,我们可以通过一个变量来接受传递出来的s变量的具体值,这样我们就能在后面继续使用。
从上图中看到,我们加了return s语句,然后将函数赋值给了result变量,也就是把return后面的s的值赋值给了result变量,这样我们就可以使用求出来的结果了。
注意
函数的返回值可以是任何类型的数据,可以是基本的数据类型,可以是列表、字典等复杂的数据类型,甚至也可以是一个函数。
其实当函数没有具体return返回值时,默认也return了一个空值None,感兴趣的朋友可以试一下。
六、三种实参类型
本篇文章的最后,我们来对实参进行一个深入的了解,给大家介绍三种参数类型:
位置实参
关键字实参
形参默认值
位置实参
在函数中,我们可以设置任意数量的参数,而我们在调用函数的时候,要求传入的每一个实参都必须能关联到函数中的所有形参。而我们的位置参数就是最简单的关联方式,就是完全按照函数中形参的顺序来关联。我们来看下面这个例子:
从上图中看出,我们定义了一个函数team_info,需要三个参数:简称、全称、简写。当我们调用team_info函数的时候,需要提供这样的三个参数,我们的“火箭”就是形参“简称”的实参,“休斯顿火箭”就是形参“全称”对应的实参,“HOU”就是形参“简写”对应的实参。
如果我们改变一下参数的顺序,来看看结果是怎样。
从上图中看出,我们改变了调用函数时,传入的实参的顺序,形参“简称”的实参变成了“HOU”,形参“全称”的实参变成了“火箭”, 形参“简写”的实参变成了“休斯顿火箭”,所以我们的结果也就发生了改变。
如果我们调用函数时,传入的实参个数大于或小于函数形参的个数,我们来看看会有什么样的结果。
上图中,我们在调用函数时,只传入了2个实参,来看一下结果。
结果报错,并且提醒我们缺少了一个“简写”参数,也能体现出我们的实参确实是按照形参的顺序来关联。
上图中,我们在调用函数时,传入了4个实参,来看一下结果。
结果依旧是报错,提示我们team_info()函数有3个参数,但是我们传入了4个。
关键字实参
在位置参数中,我们知道如果传入实参的顺序不正确,我们得到的结果也就是错误的,那么有什么办法可以让传入实参顺序不正确时,也能得到正确的结果呢?这就需要关键字参数了。
关键字参数,就是在调用函数的时候,传递给函数的参数用“形参名称=实参值”的方式来传入,这样在实参中就把实参跟指定的形参关联系起来了。
上图中,在调用team_info函数时,我们明确的指出了各个实参对应的形参,实参“HOU”对应的形参是“简写”,实参“火箭”对应的形参是“简称”,实参“休斯顿火箭”对应的形参是“全称”,这样我们就完全不需要考虑实参的顺序问题。
注意
在使用关键字实参时,一定要将形参的名称准确的写出,关键字实参的顺序也无关紧要。
形参默认值
在位置实参中,我们试过当传入的实参数量小于形参数量时会报错,那么是否存在不报错的情况呢?那就是形参默认值了。
在定义函数的时候,我们可以给形参指定一个默认值,在调用函数的时候,如果给形参提供了具体的实参,那么函数会使用指定的实参,如果不提供具体的实参,那么函数会使用形参的默认值。来分别看一下提供实参和未提供实参的情况。
上图中,我们在team_info函数中,加了一个新的参数“联赛”,并给出了一个默认值“NBA”,但我们在调用函数的时候,给联赛传了一个实参“NBDL”,所以在结果中,我们得到的是“NBDL”。
上图中,我们在调用函数的时候,只传了3个实参,并没有给形参“联赛”指定实参,所以在结果中,我们得到的是默认的“NBA”这个值。
注意
在使用默认值时,定义函数的时候,必须先列出没有默认值的形参,再列出有默认值的形参。
当我们把有默认值的形参未放在末尾时,我们来看一下错误信息。
错误信息很明显的告诉我们没有默认值的形参放在了有默认值形参的后面。
通俗理解函数
这篇文章可能有太多的名词,什么形参、实参、函数、返回值之类的,对于初次接触编程的人来说,可能有些难以理解,我就举一个很简单的生活中的例子,帮助我们理解函数。
假设我要炒一道菜,需要提供这道菜的原材料,然后炒好之后还要吃到这道菜。用我们今天学习的函数的概念来看:
参数:菜的原材料
函数体:炒菜的过程
返回值:炒好的菜
尤其是返回值,我们可以这样理解,菜炒好之后,如果没有return,那么我们就吃不到这道菜,只有return了,我们才拿到了炒好的菜,才能吃到嘴里。
这也是我的一个简单的理解,如果有不对的地方欢迎大家指出,相互学习。
探测八个蛋∣跳出手工测试的井
领取专属 10元无门槛券
私享最新 技术干货