Python之函数的参数
传参的方式只有两种:位置和关键字。
位置参数在默认参数的左边。
参数是可以是任何数据类型。
可以传递0个或多个参数。
一、形参和实参
实参:函数调用的时候传入的参数值
形参:函数定义的时候,定义的参数名
def mylen(s) 里的s是形参
leng = mylen("adfadsfasfasd") 里的adfasdfasdf是实参
def mylen(s): #参数的接收 """ 计算字符串的长度 ===函数的功能 参数s:要计算的字符串 ===参数的信息 :return:返回要计算的字符串的长度 ===返回值的信息 """ length = 0 for i in s: length += 1 return length # mylen()的括号里可以写参数,这里是参数传入的地方 leng = mylen("1234455666787") print(leng)
二、位置参数
在调用函数时,传参数:
按照位置传参
按照关键字传参
在传参的角度:按顺序定义参数
def my_max(a,b): """ 返回两个值之间的最大值 :return: """ if a > b: return a else: return b print(my_max(40,3))
关键字参数
def my_max(a,b): """ 返回两个值之间的最大值 :return: """ if a > b: return a else: return b my_max(a=40,b=1)
def lonin(user,passwd): if user == "george" and passwd == "123": return True else: return False ret = lonin('george','13') if ret: print('ok') else: print('no')
三、默认参数
默认参数可以不传值,但是,如何给默认参数传值,新的值就会覆盖定义好的旧的值。
def login(name,sex = 'male'): print('name:%s,sex:%s'%(name,sex)) login('george')
def login(name,sex = 'male'): print('name:%s,sex:%s'%(name,sex)) login('george') login('george','man')
s = 'man' def login(name,sex=s): print('name:%s,sex:%s'%(name,sex)) s='male' #不影响定义时sex的值 login('george')
默认参数:首先不要设置可变类型的默认参数
对于变化小额参数可以设置默认参数
默认的参数可以不传,不传的时候用的就是默认值
如果传,就会覆盖默认值
默认值是在定义函数的时候,就已经确定了的。
b = [] def func(a = []): #不要设置可变数据类型的默认参数 a.append(1) print(a) # func() # func() # func() # func() # func([]) # func([]) # func([]) # func([])
四、动态参数(*args,**kwargs)
*args:接收列表类型或元组类型
**kwargs:接收字典类型
位置传参,是a和b相加,而args就是一个空的元组。
def func(a,b,*args): print(a,b,args) return a+b print(func(3,1))
同样位置传参,是a和b相加,但是args就是一个有值的元组。
def func(a,b,*args): print(a,b,args) return a+b print(func(1,2,3))
按关键字传参数,c和d是关键字传参kwargs
def dun(a,b,**kwargs): print(a,b,kwargs) dun(a=1,b=2,c=333,d=333)
*args和**kwargs合用
def f(a,b,*args,**kwargs): print(a,b,args,kwargs) f(1,2,3,4,5,6,7,c=1,d=4)
参数的放置位置:位置参数,*args,默认参数,**kwargs
def fun(*args): # *args代表把散列的元素拼成元组 print(args) t = (1,2,3,4) l = [1,2,3,4] fun(*t) # *代表把一个元组、列表拆了 fun(*l) # *代表把一个元组、列表拆了
def fun(**kwargs): # **kwargs代表把关键字传来的参数拼成字典 print(kwargs) fun(a=1,b=2) d={'a':1,'b':2} fun(**d) # **kwargs代表把一个字典拆了
参数在调用函数的角度看:
1.按照位置传参
2.按照关键字传参
3.动态传参 *tuple **dic
调用函数的规则:
1.函数名() 函数名后面+圆括号就是函数的调用。 2.参数: 圆括号用来接收参数。 若传入多个参数: 应按先位置传值,再按关键字传值 具体的传入顺序应按照函数定义的参数情况而定 3.返回值 如果函数有返回值,还应该定义“变量”接收返回值 如果返回值有多个,也可以用多个变量来接收,变量数应和返回值数目一致 无返回值的情况: 函数名() 有返回值的情况: 变量 = 函数名() 多个变量接收多返回值: 变量1,变量2,... = 函数名()
总结:
参数:
实参:调用函数的时候传入的参数。
形参:定义函数的时候用于接收参数的字母。
位置参数:必须传值
def test(a,b):
print(a,b)
test(1,2)
默认参数:可以不传值
def test(x=10):
print(x)
test()
test(20)
动态参数:*args,**kwargs
*args:
def ccc(*args):#1,2,3,4,5
print(args)
ccc(1,2,3,4,5)#按位置传参数
t = (1,2,3,4,5)
ccc(t) ((1, 2, 3, 4, 5),)
ccc(*t) (1, 2, 3, 4, 5)
**kwargs:
def ddd(**kwargs):
print(kwargs)
ddd(k = 'a',j = 'b')#按关键字传参数
def eee(*args,**kwargs):
print(args,kwargs)
eee(12,123) #先按位置传参,再按关键字传参
def ccc(*args):
print('ccc:',args) #(1,2,3,4,5)
def inner(a,b,c,d,e):
print('inner',a,b,c,d,e)
inner(*args) #*(1,2,3,4,5) 打散
def inner(a,b,c,d,e):
print('inner',a,b,c,d,e)
ccc(1,2,3,4,5)
inner(1,2,3,4,5)
============================================
函数的形参与实参:
#形参即变量名,实参即变量值,函数调用时,将值绑定到变量名上,函数调用结束,解除绑定
1 #1、位置参数:按照从左到右的顺序定义的参数 2 位置形参:必选参数 3 位置实参:按照位置给形参传值 4 5 #2、关键字参数:按照key=value的形式定义的实参 6 无需按照位置为形参传值 7 注意的问题: 8 1. 关键字实参必须在位置实参右面 9 2. 对同一个形参不能重复传值 10 11 #3、默认参数:形参在定义时就已经为其赋值 12 可以传值也可以不传值,经常需要变得参数定义成位置形参,变化较小的参数定义成默认参数(形参) 13 注意的问题: 14 1. 只在定义时赋值一次 15 2. 默认参数的定义应该在位置形参右面 16 3. 默认参数通常应该定义成不可变类型 17 18 19 #4、可变长参数: 20 可变长指的是实参值的个数不固定 21 而实参有按位置和按关键字两种形式定义,针对这两种形式的可变长,形参对应有两种解决方案来完整地存放它们,分别是*args,**kwargs 22 23 ===========*args=========== 24 def foo(x,y,*args): 25 print(x,y) 26 print(args) 27 foo(1,2,3,4,5) 28 29 def foo(x,y,*args): 30 print(x,y) 31 print(args) 32 foo(1,2,*[3,4,5]) 33 34 35 def foo(x,y,z): 36 print(x,y,z) 37 foo(*[1,2,3]) 38 39 ===========**kwargs=========== 40 def foo(x,y,**kwargs): 41 print(x,y) 42 print(kwargs) 43 foo(1,y=2,a=1,b=2,c=3) 44 45 def foo(x,y,**kwargs): 46 print(x,y) 47 print(kwargs) 48 foo(1,y=2,**{'a':1,'b':2,'c':3}) 49 50 51 def foo(x,y,z): 52 print(x,y,z) 53 foo(**{'z':1,'x':2,'y':3}) 54 55 ===========*args+**kwargs=========== 56 57 def foo(x,y): 58 print(x,y) 59 60 def wrapper(*args,**kwargs): 61 print('====>') 62 foo(*args,**kwargs) 63 64 #5、命名关键字参数:*后定义的参数,必须被传值(有默认值的除外),且必须按照关键字实参的形式传递 65 可以保证,传入的参数中一定包含某些关键字 66 def foo(x,y,*args,a=1,b,**kwargs): 67 print(x,y) 68 print(args) 69 print(a) 70 print(b) 71 print(kwargs) 72 73 foo(1,2,3,4,5,b=3,c=4,d=5) 74 结果: 75 2 76 (3, 4, 5) 77 3 78 {'c': 4, 'd': 5}
定义函数的时候,我们把参数的名字和位置确定下来,函数的接口定义就完成了。对于函数的调用者来说,只需要知道如何传递正确的参数,以及函数将返回什么样的值就够了,函数内部的复杂逻辑被封装起来,调用者无需了解。
Python的函数定义非常简单,但灵活度却非常大。除了正常定义的必选参数外,还可以使用默认参数、可变参数和关键字参数,使得函数定义出来的接口,不但能处理复杂的参数,还可以简化调用者的代码。
定义默认参数要牢记一点:默认参数必须指向不变对象!
*接受列表和元组,**接受字典
小结
Python的函数具有非常灵活的参数形态,既可以实现简单的调用,又可以传入非常复杂的参数。
默认参数一定要用不可变对象,如果是可变对象,程序运行时会有逻辑错误!
要注意定义可变参数和关键字参数的语法:
*args
是可变参数,args接收的是一个tuple;
**kw
是关键字参数,kw接收的是一个dict。
以及调用函数时如何传入可变参数和关键字参数的语法:
可变参数既可以直接传入:func(1, 2, 3)
,又可以先组装list或tuple,再通过*args
传入:func(*(1, 2, 3))
;
关键字参数既可以直接传入:func(a=1, b=2)
,又可以先组装dict,再通过**kw
传入:func(**{'a': 1, 'b': 2})
。
使用*args
和**kw
是Python的习惯写法,当然也可以用其他参数名,但最好使用习惯用法。
命名的关键字参数是为了限制调用者可以传入的参数名,同时可以提供默认值。
定义命名的关键字参数在没有可变参数的情况下不要忘了写分隔符*
,否则定义的将是位置参数。
1、写函数,,用户传入修改的文件名,与要修改的内容,执行函数,完成批了修改操作
1 def modify_file(filename,old,new): 2 import os 3 with open(filename,'r',encoding='utf-8') as read_f,\ 4 open('.bak.swap','w',encoding='utf-8') as write_f: 5 for line in read_f: 6 if old in line: 7 line=line.replace(old,new) 8 write_f.write(line) 9 os.remove(filename) 10 os.rename('.bak.swap',filename) 11 12 modify_file('/Users/George/PycharmProjects/Python/a.txt','George','NB')
2、写函数,计算传入字符串中【数字】、【字母】、【空格] 以及 【其他】的个数
1 def check_str(msg): 2 res={ 3 'num':0, 4 'string':0, 5 'space':0, 6 'other':0, 7 } 8 for s in msg: 9 if s.isdigit(): 10 res['num']+=1 11 elif s.isalpha(): 12 res['string']+=1 13 elif s.isspace(): 14 res['space']+=1 15 else: 16 res['other']+=1 17 return res 18 19 res=check_str('hello name:George passowrd:111') 20 print(res)
3、写函数,判断用户传入的对象(字符串、列表、元组)长度是否大于5。
4、写函数,检查传入列表的长度,如果大于2,那么仅保留前两个长度的内容,并将新内容返回给调用者。
1 def func1(seq): 2 if len(seq) > 2: 3 seq=seq[0:2] 4 return seq 5 print(func1([1,2,3,4]))
5、写函数,检查获取传入列表或元组对象的所有奇数位索引对应的元素,并将其作为新列表返回给调用者。
1 def func2(seq): 2 return seq[::2] 3 print(func2([1,2,3,4,5,6,7]))
6、写函数,检查字典的每一个value的长度,如果大于2,那么仅保留前两个长度的内容,并将新内容返回给调用者。
dic = {"k1": "v1v1", "k2": [11,22,33,44]}
PS:字典中的value只能是字符串或列表
1 def func3(dic): 2 d={} 3 for k,v in dic.items(): 4 if len(v) > 2: 5 d[k]=v[0:2] 6 return d 7 print(func3({'k1':'abcdef','k2':[1,2,3,4],'k3':('a','b','c')}))