三、函数及参数类型
1.函数
1.1 python 传不可变对象实例
1.2python 传可变对象实例
2.参数
2.1 必需参数/位置参数
2.2 关键字参数
2.3 默认参数
2.4 不定长参数
1.函数
def 函数名(参数列表):
函数体
def max(a,b):
if a>b:
return a
else:
return b
参数传递的类型可分为不可变对象实例和可变对象实例。
不可变对象实例:
数字、字符串、元组,如数字,变量赋值 a=5 后再赋值 a=10,这里实际是新生成一个 int 值对象 10,再让 a 指向它,而 5 被丢弃,不是改变 a 的值,相当于新生成了 a。
可变对象实例:
列表、集合、字典 ,如变量赋值 la=[1,2,3,4] 后再赋值 la[2]=5 则是将 list la 的第三个元素值更改,本身la没有动,只是其内部的一部分值被修改了
1.1 python 传不可变对象实例
def change(a):
print(id(a)) # 指向的是同一个对象
a=20
print(id(a)) #指向一个新对象
a=10
print(id(a))
change(a)
print(id(a))
结果:
2247976026640
2247976026640
2247976026960
2247976026640
1.2 python 传可变对象实例
def change1(mylist):
mylist1.append([4,5,6]) #append() 添加元素
print('函数内取值',mylist1)
mylist1=[1,2,3]
change1(mylist1)
print('函数外取值:',mylist1)
结果:
[1, 2, 3, [4, 5, 6]]
[1, 2, 3, [4, 5, 6]]
2.参数
调用函数的参数可分为以下几种:
必需参数/位置参数
关键字参数
默认参数
不定长参数
2.1 必需参数/位置参数
def power(x): #x是位置参数
return x * x
>>>power(5)
25
>>>power() #报错,没有传递参数
def power(x,n): #x,n都是位置参数
num=1
for i in range(1,n+1):
num*=x
print(num)
>>>power(5,4)
625
2.2 关键字参数
关键字参数指的是调用时实参以key=value形式传入,如:
def pf(str):
print(str)
pf(str='hello') #str='hello'即为关键字参数
def person(name,age):
print('name=',name)
print('age=',age)
person(age=15,name='Sam') #函数参数的使用不需要使用指定顺序
当函数中形参为 **name 形式时,接收一个字典,函数调用的实参就要用关键字参数
def person(name, age, **kw):
print('name=',name)
print('age=',age)
for i in kw:
print(kw.key,'=',kw.value)
person('Sam',31,job=doctor,city='NewYork') #job=doctor,city='NewYork' 就是关键字参数
person('Susan',25) #给不定长参数kw未传入值
关键字参数有什么用?它可以扩展函数的功能。比如,在person函数里,我们保证能接收到name和age这两个参数,但是,如果调用者愿意提供更多的参数,我们也能收到。试想你正在做一个用户注册的功能,除了用户名和年龄是必填项外,其他都是可选项,利用关键字参数来定义这个函数就能满足注册的需求。
如希望调用是传入job和city,只能在函数内部检查kw得知,使用以下:
def person(name, age, **kw):
if 'city' in kw:
# 有city参数
pass
if 'job' in kw:
# 有job参数
pass
print('name:', name, 'age:', age, 'other:', kw)
要想限制关键字参数的名字,就可以用命名关键字参数,命名关键字在函数定义中出现,表明函数调用时需以关键字参数传入,在参数名称前加*或*不定长参数名,*或*不定长参数名之后的参数就是命名关键字参数。
区别:
关键字参数指的是函数调用中的参数,即实参以key=value形式传入;
而命名关键字指的是函数定义中的参数,即形参,通过前面加*或*不定长参数名,旨在说明*或*不定长参数名之后的参数在函数调用中要使用关键字参数(即key=value形式)传入;
如:
def person(name, age,*,job,city): #job和city前面加*,这时job和city就变成了命名关键字参数,那么在函数调用的时候job和city要以关键字参数形式传入
如:person('Sam',31,job=doctor,city='NewYork') #job=doctor,city='NewYork' 以关键字形式传入
函数的形参也可以采用不定长参数和命名关键字参数,如:
def person(name, age,*args,job,city): #*args是不定长参数,job,city是命名关键字参数,代表调用时要传入job和city字段,且以关键字参数传入
print(name, age,job,city)
person('Lisa',27,'168cm',job='teacher',city='Lindon') #命名关键字参数job和city必须传入参数名job=和city=,否则报错
person('Lisa',27,'168cm','teacher','Lindon') #'teacher','Lindon'以位置参数传入,未以关键字参数传入,报错
命名关键字也可以有缺省值,如:
def person(name, age,*,job='engineer',city): #job='engineer'是一个默认参数,调用时可不传入
print(name, age,job,city)
person('Lisa',27,city='Lindon') #调用时job未传入
2.3 默认参数
默认参数是在函数的参数(即形参)中以key=value给定了默认参数,如age=6,默认参数要指向不变对象,调用时可以给这个默认参数传值,也可以不传,使用默认参数。
如学生注册信息:
def enroll(name, gender, age=6, city='Beijing'): #age=6,city='Beijing' 就是默认参数
print('name:', name)
print('gender:', gender)
print('age:', age)
print('city:', city)
大多数学生注册时不需要提供年龄和城市,只提供必须的两个参数:
>>> enroll('Sarah', 'F')
name: Sarah
gender: F
age: 6
city: Beijing
只有与默认参数不符的学生才需要提供额外的信息:
enroll('Bob', 'M', 7)
enroll('Adam', 'M', city='Tianjin')
优点:默认参数降低了函数调用的难度,而一旦需要更复杂的调用时,又可以传递更多的参数来实现。无论是简单调用还是复杂调用,函数只需要定义一个。
设置默认参数时,有几点要注意:
一是必选参数在前,默认参数在后,否则Python的解释器会报错。
二是如何设置默认参数。
当函数有多个参数时,把变化大的参数放前面,变化小的参数放后面。变化小的参数就可以作为默认参数。
有多个默认参数时,调用的时候,既可以按顺序提供默认参数,如enroll('Bob', 'M', 7),传了name,geder和age,age使用传的参数,不使用默认参数6,city没有传,使用默认参数'Beijing';
也可以不按顺序提供部分默认参数。当不按顺序提供部分默认参数时,需要把参数名写上。比如调用enroll('Adam', 'M', city='Tianjin'),传了name,geder和city,age没有传,使用默认参数6
默认参数必须指向不变对象!
否则可能出现以下情况:
def add_end(L=[]):
L.append('END')
return L
正常调用:
>>> add_end([1, 2, 3])
[1, 2, 3, 'END']
>>> add_end(['x', 'y', 'z'])
['x', 'y', 'z', 'END']
使用默认参数多次调用:
>>> add_end()
['END']
>>> add_end()
['END', 'END']
>>> add_end()
['END', 'END', 'END']
原因分析:
Python函数在定义的时候,默认参数L
的值就被计算出来了,即[]
,因为默认参数L
也是一个变量,它指向对象[]
,每次调用该函数,如果改变了L
的内容,则下次调用时,默认参数的内容就变了,不再是函数定义时的[]
了。
可如下调用,解决该问题:
def add_end(L=None):
L.append('END')
return L
多次调用:
>>> add_end()
['END']
>>> add_end()
['END']
>>> add_end()
['END']
2.4 不定长参数
可变参数就是传入的参数个数是可变的,在函数的参数(即形参)前加*即表示可变参数,调用是可变参数可传入多个或0个。
加了星号 * 的参数会以元组(tuple)的形式导入
def printinfo(arg1,*vartuple ): # 加了星号 * 的参数会以元组(tuple)的形式导入,存放所有未命名的变量参数
print('arg1=',arg1) #arg1= 4
print('vartuple =',vartuple ) #arg2= (5, 6)
printinfo(4,5,6)
def printinfo(arg1,*vartuple ): # 加了星号 * 的参数会以元组(tuple)的形式导入,存放所有未命名的变量参数
print('arg1=',arg1) #arg1= 4
for i in vartuple:
print(i)
printinfo(4) #如果在函数调用时没有指定参数,它就是一个空元组。我们也可以不向函数传递未命名的变量
printinfo(4,5,6)
加了两个星号 ** 的参数会以字典的形式导入
def printinfo(arg1,**vardict): # 加了两个星号 ** 的参数会以字典的形式导入
print('arg1=',arg1) #arg1= 1
print('vardict =',vardict ) #vardict = {'a': 2, 'b': 3}
printinfo(1, a=2,b=3)
如传参是个list或tuple,可传参时使用*列表名/元组名
def printinfo(arg1,*vartuple ): # 加了星号 * 的参数会以元组(tuple)的形式导入,存放所有未命名的变量参数
print('arg1=',arg1) #arg1= 4
print('vartuple =',vartuple ) #arg2= (5, 6)
nums=[4,5,6]
printinfo(*nums) #传参是list
nums1=(1,2,3)
printinfo(*nums1) #传参是tuple
本文来自于以下文章的学习笔记:
https://www.liaoxuefeng.com/wiki/1016959663602400/1017261630425888
https://www.runoob.com/python3/python3-function.html