函数基础
一、函数定义:函数就是具备某一功能的工具,事先将工具准备好就是函数的定义,遇到应用场景拿过来用就是调用函数。
函数的介入好处:1),使代码的结构更加清晰,可读性更高;2),避免相同功能的代码块重复出现,减少了代码冗余;3),增加了代码的扩展性,不然如果一个应用程序在多处使用该功能块,必须重复的检查修改,统一管理及维护难度极大。
函数使用的原则:必须先定义,再调用。定义了的函数可以在任意位置调用,但是次序不能颠倒。 定义阶段只检测语法,不执行代码。
在上图中,1阶段就是定义函数阶段,在这个阶段没有执行2阶段的调用,就只检测函数体内部代码语法;2阶段用函数名加括号,调用函数,才开始执行函数体内部代码,这里就相当于变量名赋值一样,值在内存中有一块内存空间,需要绑定一个变量名才能访问到它。而函数名加括号(test())就是用它找到函数体内要执行的代码。在3阶段调用代码时才会报错。
函数名的命名规范:同变量名一样,只能以字母、数字、下划线组成,不能与关键字冲突,另外还要见名知意。
定义函数的三种方式:
1).无参函数:定义函数时参数是函数接收外部传值的一种媒介,其实就是一个变量名;在函数定义阶段括号内没有参数,称为无参函数;在定义时没有参数,意味着在调用阶段也无需传入参数。
如果函数体代码逻辑不需要外部传值,就必须定义成无参函数。
def func(): print('from func') func()
2). 有参函数:在函数定义阶段括号内有参数,称为有参函数。需要注意的是:定义时有参,意味着调用时也必须传入参数。
如果函数体代码逻辑需要依赖外部传入的值,必须得定义成有参函数。
def sum_self(x, y): """求和""" res = x+y print(res) sum_self(1,2) # 3
3). 空函数:当你只知道你需要实现某个功能,但不知道该如何用代码实现时,你可以暂时写个空函数,然后先实现其他的功能。
def func(): pass
二、函数分类
1、内置函数:为方便开发,Python解释器事先给我们定义好的函数就是内置函数,使用时无需定义。比如:len()、max()、sum()等。
1 s = 'hello world' 2 l = [1,2,3,4,5,6] 3 my_len() 4 print(len(s),len(l))
2、自定义函数:Python解释器内的内置函数功能是有限的,这时我们就需要根据自己的需求定义自己的函数,这种函数就是自定义函数。
s = 'hello world' l = [1,2,3,4,5,6] def my_len(): # 自定义函数 此行是函数的定义 n = 0 for i in s: n += 1 print(n) # res = len(s) # print(res) res = my_len() print(res) #没有返回值,返回的是None len(s) #函数的调用 len(l) #函数的调用
以上是自定义调用函数没有返回值的情况。。。。
下面说一下函数有返回值的情况,函数返回给调用者值的话,要用return关键字,共分为一下4种:
1),不写return;
def func():
print('fhj','指定')
res=func()
print(res) #不写return返回值是none
2)只写return;
3)写return none;
4)return返回一个值;
5),return返回多个值;结果是元组,不可修改。
总结:
1.所有的函数都有返回值,无论你写不写return
python中所有的函数都有返回值 不写的情况下默认返回None
2.光写return 或者return None并不是为了考虑返回值 而是为了结束函数的运行
二、函数的参数
1,形参:在函数的定义阶段 括号内写的变量名 叫做该函数的形式参数 简称 形参
2,实参:在函数的调用阶段 括号内实际传入的值 叫做实际参数 简称 实参
注意:形参和实参的绑定关系只在函数的调用阶段有效,函数运行结束关系自动解除
只在函数内部有效 函数外部无任何影响
函数构架格式:
def 函数名(形参1,形参2,,,,)
'''函数的注释 用来描述该函数的作用以及各个形参的类型'''
函数体代码1
函数体代码2
...
return 函数的返回值
"""
三、位置参数
位置参数:在函数定义阶段按照位置从左往右依次书写的变量名 叫做函数位置形参,位置形参在调用的时候 必须为其传值
位置实参:在函数的调用阶段 传入的参数会按照位置一一对应给形参,个数不能多也不能少。
位置实参给形参的传参的方式:1),按位置传参,2)关键字传参;
注意:如果是位置传参合关键字传参混用的时候,位置实参在前,关键字实参在后。
默认值参数::在函数的定义阶段,形参(变量名)就已经被赋值了
注意:在调用的时候可以不为默认值形参传值,默认使用定义阶段就已经绑定的值, 在调用的时候如果可以给默认值形参传值 传了那么就使用你传的值, 在定义阶段 默认值形参必须放在位置形参的后面。
函数在定义阶段 内部所使用的变量都已经初始化完毕了;不会因为调用的位置的变化 而影响到内部的值(暂时可忽略);函数无论在什么地方被调用,都会跑到函数定义阶段去执行代码,形参中用到的值都是往函数定义阶段代码往上找;在定义阶段默认参数必须在位置参数的后边。
可变长参数:站在调用函数传递实参的角度 实参的个数不固定的情况,也就意味形参也不固定
站在形参的角度 可以用*和**来接收多余的(溢出的)位置参数和关键字参数
站在形参的角度看*
形参中的*会将多余的(溢出的)位置实参 统一用元组的形式处理 传递给*后面的形参名
站在实参的角度看*
*会将实参列表或元组打散,给形参一一赋值,多余的被*后形参接收,*在形参中只能接收多余的位置实参 不能接收关键字实参
*只能将列表 元组 集合 字符串,*的内部你可以看成是for循环
站在形参的角度看**
*会接收所有多余的关键字参数 并将关键字参数 转换成字典的形式 字典的key就是关键字的名字,字典的value就是关键字的名字指向的值 将字典交给**后面的变量名。
站在实参角度看*,
图中**将字典拆分成类似于关键字传值的方式,x=1,y=32,z=4
命名关键字参数:函数定义阶段写在*与**可变长参数之间的形参,上图中可以看出,位置实参前两个,一个给了形参x,一个传给了默认形参,剩下的位置实参让*后args接收了,而给*和**之间的z=3和m传值必须用关键字传参的方式,多余的关键字参数被**接收。其实z和m都是命名关键字参数 不是默认值参数和位置参数,所以不需要讲究像给形参传值那样位置参数在关键字参数的前面。