Python函数基础
函数基础
第1章 函数知识体系
1.1 什么是函数?
具备某一功能的工具
好比:修理工=程序员
想使用工具,需要事先准备好,然后在拿工具出来使用
要想使用函数,就先自己定义,然后在使用
1.2 为什么要用函数?
原因:
1、代码组织结构不清晰,可读性差
2、遇到重复的功能只能重复编写实现代码,代码冗余
3、功能需要扩展时,需要找出所有实现该功能的地方修改 ,无法统一 管理且维护难度极大
1.3 函数的分类:内置函数与自定义函数
内置函数:
为了方便我们的开发,针对一些简单的功能,python解释器已经为我们定义好了的函数即内置函数。对于内置函数,我们可以拿来就用而无需事先定义,如len(),sum(),max()
自定义函数:
很明显内置函数所能提供的功能是有限的,这就需要我们自己根据需求,事先定制好我们自己的函数来实现某种功能,以后,在遇到应用场景时,调用自定义的函数即可。
1.4 定义函数
没事先定义函数而直接调用,就相当于引用一个不存在的变量名
定义阶段:在定义阶段只检测语法,不执行函数体代码。
调用阶段:根据函数名找到函数的内存地址,然后执行函数体代码。
定义阶段示例:
def func():
xxx
print('sadfsadf'
(定义阶段会检测语法,报错)
调用阶段示例:
def bar():
print('from bar')
def foo():
print('from foo')
bar()
foo()
#定义阶段
def foo():
print('from foo')
bar()
def bar():
print('from bar')
#调用阶段
foo()
#定义阶段
def foo():
print('from foo')
bar()
#调用阶段
foo()
def bar():
print('from bar')
def max2(x,y):
if x > y:
return x
else:
return y
res=max2(10,3)*100
print(res) ###打印的值等于1000
1.4.1 如何而自定义函数
1.4.1.1 语法:
def 函数名(参数1,参数2,参数3,...):
'''注释'''
函数体
return 返回的值
def:定义函数的关键字
函数名:是用来调用函数的,
函数名的命名必须能反映出函数的功能
文档描述:推荐写上,来增强函数的可读性
代码块:函数功能实现代码
return:函数的返回值
强调:函数名要能反映其意义(功能)
1.4.1.2 函数使用的原则:先定义,再调用
函数即“变量”(打个比喻为变量,其实函数与变量并不是同一个概念),“变量”必须先定义后引用。未定义而直接引用函数,就相当于在引用一个不存在的变量名
1.4.1.3 函数在定义阶段都干了哪些事?
#1、无参:应用场景仅仅只是执行一些操作,比如与用户交互,打印
#2、有参:需要根据外部传进来的参数,才能执行相应的逻辑,比如统计长度,求最大值最小值
#3、空函数:设计代码结构
1.4.1.4 定义函数的三种形式
有参函数:参数是含数代码 用来接收外部传入值得
当函数体的代码逻辑不需要函数的调用者参入
示例:
def max2(x,y): #x=100,=y101
# x=10
# y=3
if x > y:
print(x)
else:
print(y)
max2(100,101)
无参函数:函数体的代码逻辑不需要函数的调用者掺入值的情况下,就无参
def func():
print('----------------------')
print('---soft run-----------')
print('----------------------')
def interactive():
name=input('username>>: ').strip()
pwd=input('password>>: ').strip()
print(name,pwd)
interactive() #定义时无参,意味着调用时也无须传入参数
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1.5 调用函数
1.5.1 如何调用函数
函数的调用:函数名加括号
1 先找到名字
2 根据名字调用代码
1.5.2 函数的返回值
什么时候应该有返回值:函数体代码运行完毕后需要有一个返回结果给调用者
1 没有return,返回值None
def func():
pass
res=func()
print(res)
2 return后跟一个值,返回该值本身
def func1():
return 1
res=func1()
print(res)
3 return可以逗号分隔,返回多个值,会返回一个元组给调用者
def func2():
return 1,2,[1,2,3]
res=func2()
print(res)
return注意点:
1、return返回值的值,没有类型限制
2、return是函数结束的标志,函数内可以写多个return,但执行一次,函数就立刻结束,并把return后的值作为本次调用的返回值
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1.6 函数的参数:
1.6.1 形参和实参
形参(形式参数):指的是
在定义函数时,括号内定义的参数,形参其实就变量名
实例:
#x,y是形参
def func(x,y): #x=10,y=11
print(x)
print(y)
实参(实际参数),指的是
在调用函数时,括号内传入的值,实参其实就变量的值
实例:
#10,11是实参
def func(x,y): #x=10,y=11
print(x)
print(y)
func(10,11)
注意:
实参值(变量的值)与形参(变量名)的绑定关系只在函数调用时才会生效/绑定在函数调用结束后就立刻解除绑定.
1.6.2 位置参数:
什么是位置参数?
位置即顺序,位置参参数指的就是按照从左到右的顺序依次定义的参数.
1.6.2.1 位置形参
定义:在定义函数时,按照位置定义的形参,称之为位置形参
def foo(x,y,z):
print(x,y,z)
注意:
位置形参的特性是:在调用函数时必须为其传值,而且多一个不行,少一个也不行
1.6.2.2 位置实参
定义:在调用函数时,按照位置定义的实参,称为位置实参
注意:位置实参与形参一一对应
示例:
def foo(x,y,z):
print(x,y,z)
foo(1,3,2)
1.6.3 关键字参数
什么是关键字参数?
调用函数时,按照key=value的形式定义的实参,称为关键字参数
注意:
1、相当于指名道姓地为形参传值,意味着即便是不按照顺序定义,仍然能为指定的参数传值
示例:
def foo(x,y,z): print(x,y,z) foo(1,2,3) foo(x=2,y=1,z=3) foo(z=2,aaa=1) #报错(foo() got an unexpected keyword argument 'aaa')
2、在调用函数时,位置实参与关键字实参可以混合使用,但必须遵守形参的规则
示例:
def foo(x,y,z): print(x,y,z) foo(1,z=3,y=2) foo(1,z=3)报错(TypeError: foo() missing 1 required positional argument: 'y')
3、不能为同一个形参重复传值
示例:def foo(x,y,z): print(x,y,z) foo(1,x=1,y=3,z=2)#报错
4、位置实参必须放到关键字实参的前面
示例:
def foo(x,y,z): print(x,y,z) # foo(y=3,z=2,1)#报错 foo(1,y=3,z=2)
1.6.4 默认参数
在定义阶段,已经为某个形参赋值,那么该形参就称为默认参数
注意:
1、定义阶段已经有值,意味着调用阶段可以不传值
示例:
def register(name,age,sex='male'): print(name,age,sex) register('egon',18,) register('alex',73,'female') register('wxx',84,) register('xxx',84) register('yy',84)
2、位置形参必须在默认参数的前面
示例:
def func(y=1,x): #错误
pass
3、默认参数的值只在定义阶段赋值一次,也就是说默认参数的值再定义阶段就固定死了
示例:
m=10 def foo(x,y=m): print(x,y) m='aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' foo(1) foo(1,11)
4、记住:默认参数的值应该设置为不可变类型
def register(name,hobby,l=[]):
l.append(hobby)
print(name,l)
register('wxx','play') # wxx ['play']
register('alex','read') # alex ['read']
register('egon','music') # alex ['music']
# register('wxx','play',[]) # wxx ['play']
# register('alex','read',[]) # alex ['read']
# register('egon','music',[]) # alex ['music']
def register(name,hobby,l=None):
if l is None:
l=[]
l.append(hobby)
print(name,l)
register('alex','play')
register('wxx','whaaa'
)
应用:
对于经常需要变化的值,需要将对应的形参定义成位置形参
对于大多数情况值都一样的情况,需要将对应的形参定义成默认形参
1.6.5 变长度参数
什么是可变长度参数?
可变长度指的参数的个数可以不固定,实参有按位置定义的实参和按关键字定义的实参,
所以可变长的实参指的就是按照这两种形式定义的实参个数可以不固定,然而实参终究是要给形参传值的所以形参必须有两种对应的解决方案来分别处理以上两种形式可变长度的实参
形参:
*
**
1.6.5.1 形参里包含:
1、*会将溢出的位置实参全部接收,然后保存成元组的形式赋值给args
def foo(a,b,c,d,e,*args):
print(a,b,c,d,e)
print(args)
foo(1,2,3,4,5,6,7,8,1,1,1,2,)
2、**会将溢出的关键字实参全部接收,然后保存成字典的形式赋值给kwargs
def foo(x,y,z,**kwargs):
print(x,y,z)
print(kwargs)
foo(x=1,y=2,z=3,a=1,b=2,c=3)
1.6.5.2 实参里包含:
一旦碰到实参加*,就把该实参的值打散
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
一旦碰到实参加**,就把该实参的值打散
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
组合使用:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1.6.6 补充知识
*的应用场景:
def sum2(*args):
res=0
for num in args:
res+=num
return res
print(sum2(1,2,3,4,5,6,8,9,11))
**的应用场景:
示例:
def auth(name,pwd,**kwargs):
print(name)
print(pwd)
print(kwargs)
auth('egon','123')
auth(name='engon',pwd='123',group='aaa')
def foo(x,y=1,*args,z,**kwargs):
pass
def foo(x,y=1):
pass
def foo(x,*args,**kwargs):
pass
1.6.7 命名关键字参数
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
什么是命名关键字参数?
格式:在*后面参数都是命名关键字参数
特点:
1 必须被传值
2 约束函数的调用者必须按照key=value的形式传值
3 约束函数的调用者必须用我们指定的key名
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)