函数基础
主要内容:
- 函数简单介绍
- 函数定义
- 函数调用
- 函数参数
1. 函数简单介绍:
什么是函数? 我们在编写程序的过程中,经常会遇到多个数据或处理过程需要同样的代码逻辑去处理,为了我们方便,减少代码重复率,我们介意把这种同样处理逻辑的代码放在一起,作为一个数据处理方式方便后面调用, 而这种像处理工具一样的一段代码,就被我们定义为函数。 为什么要用函数? #1、通过对函数的定义,可以使我们的代码逻辑结构更清晰,增强可读性,就好比你要工作了,一排排你要使用的工具放在你的面前,你可以直接使用 #2、 减少代码的重复性,实现代码冗余,处理相同的工作,使用同样的工具,只需要去调用,不需要重新编写工具 #3、 增加代码的可拓展性,一个工具不适应现在的工作了,只需要给工具进行改良,然后调用就行,不用每一步都要改良工具,然后进行工作
函数的分类: #1、 内置函数: 为了方便我们开始,在创建python的时候就在python解释器里面加入了我们平时开发常用的简单的工具,这些工具就是内置函数,解释器中的这些内置函数我们可以拿来就用,不用事先定义,比如常见的len() max() sum()等 #2、 自定义函数 从名字表面意思就能理解到,自定义函数需要我们自己事先定义好,具备动能的函数,然后再被调用,因为内置函数只能满足我们简单的需求,复杂的需要处理自己业务逻辑的函数需要自己定义
2. 函数定义
#定义函数语法 def 函数名(参数1,参数2,参数3,....,*args,**kwargs) #当然还可以没有参数 '''注释''' 函数体 #即函数实现功能的定义 return 返回值 #返回值肯定存在,没有定义return默认返回None #为了书写代码规范,函数名尽量反应函数的意义和作用
函数使用的原则是:必须先定义,才能被调用
我们在使用函数时,一定要明确地区分定义阶段和调用阶段 #定义阶段 def foo(): print('from foo') bar() def bar(): print('from bar') #调用阶段 foo()
并且函数在定义阶段只检测语法,但是代码逻辑错误只有执行之后才能知道
定义函数的三种形式: #1、 无参:应用场景在仅仅只执行一些操作,不如与用户交互和打印 def tell_msg(): #无参数 print('hello world') #输出打印 #2、 有参:函数内部需要外部传入参数才能执行相应的逻辑,比如统计长度,比较大小,收集处理数据等。 def tell_tag(tag,n): #有参数 print(tag*n) tell_tag('*',12) #执行输出************ #3、 空函数:在程序结构规划和定义的时候,用于占位和结构规划 def foo(): pass #结论: #1、定义时无参,意味着调用时也无需传入参数 #2、定义时有参,意味着调用时则必须传入参数
3. 函数调用
#1.调用函数: 函数名() #函数名与定义的函数名一致, print(函数名) #实际是输出这个函数对应的内存地址,而函数名后面加(),括号的作用是通过这个地址找到函数体本身并且执行。 #2.函数的返回值 还记得我们之前说到的return返回值么? 函数定义中: 无return,默认返回None return 1个值 -> 函数执行完毕之后返回这个值 return 逗号隔开多个值 -> 函数执行完毕之后返回一个由这多个值组成的元组 #为什么需要返回值? 在调用函数执行之后,经过这个工具处理我们需要得到一个结果或者生物被用在其他地方使用,所以在这种时候函数执行后需要一个返回值,当然,也存在不需要返回值的时候,比如函数只是单纯的执行一下打印和用户交互功能的时候。 #3.函数调用的形式: 1 语句形式:foo() 2 表达式形式:3*len('hello') 3 当中另外一个函数的参数:range(len('hello'))
4. 函数参数
一、 参数分两大类: 形参与实参 #形参即变量名,实参即变量值,函数调用时,将值绑定到变量名上,函数调用结束,解除绑定 def foo(x) #括号中x为形参,即变量名 print(x) foo(1) #括号中的1为实参,即变量值,调用的过程中就是完成x=1的赋值操作
根据具体应用分类为分为以下几种: #1、位置参数:按照从左到右的顺序定义的参数 位置形参:必选参数 位置实参:按照位置给形参传值 def foo(x, y, z, a, b, c): print(x) print(y) print(z) print(a) print(b) print(c) foo(1, 2, 3, 4, 5, 6) #按照位置顺序给形参赋值,多一个少个实参都会报错 位置参数总结:传参的过程中,实参和形参的个数,位置和顺序必须一一对应,否则会报错,当然,位置参数中插有其他参数也会报错,必须严格要求,一一对应。 #2、关键字参数:按照key=value的形式定义的实参 无需按照位置为形参传值 注意的问题: 1. 关键字实参必须在位置实参右面 2. 对同一个形参不能重复传值 def foo(x, y, z): print(x) print(y) print(z) foo(x=1, y=2, z=3) 或 foo(y=2, z=3, x=1) #关键字参数不需要遵守顺序 #3、默认参数:形参在定义时就已经为其赋值 可以传值也可以不传值,经常需要变得参数定义成位置形参,变化较小的参数定义成默认参数(形参) 注意的问题: 1. 只在定义时赋值一次 2. 默认参数的定义应该在位置形参右面 3. 默认参数通常应该定义成不可变类型 def foo(x, y, z=3): print(x) print(y) print(z) #z会默认输出3 foo(x=1, y=2) #4、可变长参数: 可变长指的是实参值的个数不固定 而实参有按位置和按关键字两种形式定义,针对这两种形式的可变长,形参对应有两种解决方案来完整地存放它们,分别是*args,**kwargs ===========*args=========== def foo(x,y,*args): #符号*会把后面多出的3,4,5实参转化为元组(3, 4, 5)然后赋值给变量名args print(x,y) print(args) #输出结果为(3, 4, 5) foo(1,2,3,4,5) def foo(x,y,*args): #这一步的*会把传过来的单个位置参数3,4,5转化成一个元组(3, 4, 5)赋值给args print(x,y) print(args) #输出结果为(3, 4, 5) foo(1,2,*[3,4,5]) #这一步符号*会把列表裁开成单个的位置参数3,4,5 def foo(x,y,z): #按照位置参数的方式赋值,x=1.y=2,z=3 print(x,y,z) foo(*[1,2,3]) #这一步符号*会把列表裁开成单个的位置参数1,2,3 def foo(x,y,z,*args): #这一步会把位置参数形式传过来的3赋值给z,然后符号*将多出来的4,5转化为元组(4, 5) print(x,y,z) #输出结果为1,2,3 print(args) #输出结果为(4, 5) foo(1,2,*[3,4,5]) #这一步符号*会把列表裁开成单个的位置参数3,4,5 ===========**kwargs=========== def foo(x,y,**kwargs): #这一步关键字参数会把2赋值给y,然后符号**会把多出来的关键字参数转化为{'a':1, 'b':2, 'c':3}这个字典,赋值给变量名kwargs print(x,y) print(kwargs) #结果输出{'a':1, 'b':2, 'c':3} foo(1,y=2,a=1,b=2,c=3) def foo(x,y,**kwargs): #符号**会把多出来的关键字参数转化为{'a':1, 'b':2, 'c':3}这个字典,赋值给变量名kwargs print(x,y) print(kwargs) foo(1,y=2,**{'a':1,'b':2,'c':3}) #这一步符号**会先把字典拆为a=1,b=2,c=3的关键字实参形式进行传参 def foo(x,y,z): print(x,y,z) foo(**{'z':1,'x':2,'y':3}) #这一步符号**会先把字典拆为z=1,x=2,y=3的关键字实参形式进行传参 ===========*args+**kwargs=========== def foo(x,y): print(x,y) #输出1,2 好好想想为什么? def wrapper(*args,**kwargs): print('====>') foo(*args,**kwargs) wrapper(1,y=2)
#5、命名关键字参数:*后定义的参数,必须被传值(有默认值的除外),且必须按照关键字实参的形式传递
可以保证,传入的参数中一定包含某些关键字
def foo(x,y,*args,a=1,b,**kwargs):
print(x,y)
print(args)
print(a)
print(b)
print(kwargs)
foo(1,2,3,4,5,b=3,c=4,d=5)
结果:
1
2
(3, 4, 5)
1
3
{'c': 4, 'd': 5}

浙公网安备 33010602011771号