函数基础
-
引子
-
定义函数
-
调用函数
-
函数返回值
-
函数参数
一、引子
1.不用函数会引发什么问题?
代码的组织结构不清晰,可读性差;
遇到重复的功能只能重复编写实现代码,代码冗余;
功能需要扩展的时候,需要找出所有实现该功能的地方修改,无法统一管理且维护难度极大;
举个例子:
比如说,len方法突然不能直接用了,然后现在有一个需求,让你计算'hello world'的长度,你怎么计算?
这个需求对于现在的你其实不难,我们一起来写一下。
s1 = "hello world" length = 0 for i in s1: length = length+1 print(length)
好了,功能实现了,非常完美。然后现在又有了一个需求,要计算另外一个字符串的长度,"hello eva".
于是,这个时候你的代码就变成了这样:
s1 = "hello world" length = 0 for i in s1: length = length+1 print(length) s2 = "hello eva" length = 0 for i in s2: length = length+1 print(length)
这样确实可以实现len方法的效果,但是总感觉不是那么完美?为什么呢?
首先,之前只要我们执行len方法就可以直接拿到一个字符串的长度了,现在为了实现相同的功能我们把相同的代码写了好多遍 —— 代码冗余
我们就想啊,要是我们能像使用len一样使用我们这一大段“计算长度”的代码就好了。这种感觉有点像给这段代码起了一个名字,等我们用到的时候直接喊名字就能执行这段代码似的。要是能这样,是不是很完美啊?这时候就需要我们的函数出场啦!
2.函数是什么?
想象生活中的例子,修理工需要事先准备好工具箱里面放好锤子、扳手、钳子等工具,然后遇到锤钉子的时候,拿上锤子用就可以,而无需临时再造一把;
修理工 -------> 程序员
具备某功能的工具 --------> 函数
要想使用工具,需要事先准备好,然后拿来就用且可以重复使用
想要用函数,需要先定义,再使用;.
那么我们如何用函数方式解决上面问题呢?
现在就教大家一个既能,让你们把代码装起来。
def mylen(): s1 = "hello world" length = 0 for i in s1: length = length+1 print(length)
这样我们就定义了一个函数,怎么使用呢,只需要mylen()就可以实现函数调用。
3.函数分类
a.内置函数
为了方便我们的开发,针对一些简单的功能,python解释器已经为我们定义好了的函数即内置函数,对于内置函数,我们可以拿来就用而无需事先定义,另一篇文章里专门有内置函数的讲解;
b.自定义函数
毕竟是内置函数,所能提供的功能是有限的,这样就需要我们自己根据需求,事先定义好我们自己的函数来实现某功能,以后在遇到应用场景时,调用自定义的函数即可。
二、定义函数
1.如何定义函数,函数的结构体。
## 语法 def 函数名 (参数1,参数2,参数3,...): '''注释''' 函数体 return 返回的值 ## 函数名要有意义 ##注意: #1.def关键字开头,空格之后接函数名称和圆括号(),最后还有一个“:”; #2.def是固定的,不能变,必须是连续的def三个字母,不能分开; #3.空格,为了将def关键字和函数名分开,必须空开,也可以使用2个或多个空格,正常人都是一个空格; #4.函数名,函数名只能包含字符串,下划线和数字且不能以数字开头,要想变量一样的去定义; #5.括号,是必须加的,不要问为什么,加上就对了; #6.每一个函数都应该对功能和参数进行相应的说明,应该写在函数下面的第一行,以增强代码的可读性; #7.调用,就是函数名(),一定要记得加上括号,不加括号获取的就是函数的内存地址了。
例如:
def auth(user,password): ''' auth function user:用户名 password:密码 return:认证结果 ''' if user == "zjk" and password == "123": return 1 user = input(user:).strip() password = input(pws:).strip() res = auth(user,password) print(res)
2.函数的使用原则:先定义,再调用;
函数即“变量”,变量必须先定义后饮用,未定义而直接引用函数就相当于在引用一个不存在的变量;用例子来说明:
#测试1. >>> def foo(): ... print("from foo") ... bar() ... >>> foo() from foo Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 3, in foo NameError: name 'bar' is not defined #报错,提示bar这个函数没有定义; #测试2. >>> def bar(): ... print("from bar") ... >>> def foo(): ... print("from foo") ... bar() ... >>> foo() from foo from bar ##正常执行; #测试3 >>> def foo(): ... print("from foo") ... bar() ... >>> def bar(): ... print("from bar") ... >>> foo() from foo from bar #说明在代用函数时,函数是不分前后的,但需要注意的时,函数的使用,必须遵循原则,先定义,后使用;不然的话代码调用函数的时候,函数却还没有加载到内存;所以,我们在使用函数时,一定要明确地区分定义阶段和调用阶段。 #定义阶段 >>> def foo(): ... print("from foo") ... bar() ... >>> def bar(): ... print("from bar") ... >>> foo() #调用阶段 >>> foo() from foo from bar
3.函数在定义阶段都干了啥子事情?
只检测语法,不执行代码;
也就是说,语法错误在函数定义阶段就 会检测出来,而代码的逻辑错误只有在执行的时候才知道;
4.定义函数的三种形式;
无参:应用场景仅仅只是执行一些操作,比如与用户交互,打印;
有参:需要根据外部传来的参数,才能执行相应的逻辑,比如统计长度,求最大值最小值;
空函数:设计代码结构;
例如:
#定义阶段 def tell_tag(tag,n): #有参数 print(tag*n) def tell_msg(): #无参数 print('hello world') #调用阶段 tell_tag('*',12) tell_msg() tell_tag('*',12) ''' ************ hello world ************ ''' #结论: #1、定义时无参,意味着调用时也无需传入参数 #2、定义时有参,意味着调用时则必须传入参数
def auth(user,password): ''' auth function :param user: 用户名 :param password: 密码 :return: 认证结果 ''' pass def get(filename): ''' :param filename: :return: ''' pass def put(filename): ''' :param filename: :return: ''' def ls(dirname): ''' :param dirname: :return: ''' pass #程序的体系结构立见
三、调用函数
1.调用函数
函数的调用:函数名加括号,func()
a.先找到名字
b.根据名字调用代码
2.函数返回值
return 是一个关键字,这个词翻译过来就是“返回”,所以我们管写在return后面的值叫“返回值",一旦遇到return,结束整个函数;
三种类型,无返回值,返回1个值,返回多个值;
无返回值:函数体中没有return,或者return后没有跟任何值,这时此函数会返回一个None;
返回1个值:return 后跟一个值;
返回多个值:return后跟多个值,多个值之间用逗号分隔,此时return返回的是一个元组类型;
那么,什么时候该有返回值呢?
调用函数,经过一系列的操作,最后要拿到一个明确的结果,则必须要有返回值;
通常有参函数需要有返回值,输入参数,经过计算,得到一个最终的结果;
什么时候不需要有返回值?
调用函数,仅仅只是执行一系列的操作,最后不需要得到什么结果,则无需有返回值;
通常无参函数不需要有返回值;
3.函数调用的三种形式
a.语句形式:foo()
b.表达式形式:3 * len("hello")
c.当中另外一个函数的参数:range(len("hello"))
4.函数结束的方式:
a.遇到return结束整个函数;
b.函数体正常执行完毕,整个函数也会结束;
四、函数的参数