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')
View Code
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)
View Code
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]))
View Code
5、写函数,检查获取传入列表或元组对象的所有奇数位索引对应的元素,并将其作为新列表返回给调用者。
1 def func2(seq):
2 return seq[::2]
3 print(func2([1,2,3,4,5,6,7]))
View Code
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')}))
View Code