晓夏

YoungCheung

Zhang Sir's technical way

python函数的参数

浏览量:660

我们最开始接触到的函数是不带参数的函数,例如: 

def parm(str):
    print('the parm is' ,str) 
parm('hello world!')

调用参数时可以使用一下参数类型:
1、必须参数;
2、关键字参数;
3、默认参数;
4、可变参数;
5、组合参数;

1、函数的参数

1.1 必须参数

必须参数必须以正确参数顺序传入参数,调用时数量必须和声明时一样。
例:

def parm(str):
    print('the parm is' ,str) 
parm('hello world!')

输出:the parm is hello world!,
如果我们不传入参数,那么结果如下:

def parm(str):
    print('the parm is' ,str)

parm()
TypeError: parm() missing 1 required positional argument: 'str'

如果我们多传入一个参数会怎么样呢?

def parm(str):
    print('the parm is' ,str)

parm('hello','world')

TypeError: parm() takes 1 positional argument but 2 were given

通过以上示例我们可以看到,对于定义parm()函数,不传入或者多传入参数都会报错,所以对于此类函数必须传入对应正确个数参数。

1.2 关键字参数

关键字参数和函数调用关系紧密,函数调用使用关键字参数确定传入的参数值。
使用关键字参数允许调用函数时参数的顺序与声明时不一致,因为python解释器能够用参数名匹配参数值。
例:

def personinfo(age,name):    print('age:', age)
    print('name:',name)
    return
print('按照参数顺序传入')
personinfo('23','zhangyang')
print('不按参数照顺序传入,指定参数名')
personinfo(name='zhangyang',age=23)
print('按参数照顺序传入,指定参数名')
personinfo(age=23,name='zhangyang')

输出结果:

按照参数顺序传入
age: 23
name: zhangyang
不按参数照顺序传入,指定参数名
age: 23
name: zhangyang
按参数照顺序传入,指定参数名
age: 23
name: zhangyang

以上结果显示,对于personinfo()函数,只要指定参数名,输入参数的顺序对结果没有影响,都能得到正确的结果。

1.3 默认参数

调用函数时,如果没有传入参数,那么就会使用默认的参数。
使用默认参数,就是在定义函数时,给参数一个默认的值,如果没有给调用的函数的参数赋值,调用的函数就会使用这个默认值。

def defaultparm(name,age=23):
    print('name:',name)
    print('age:',age)    
    return
defaultparm('zhangyang')

输出结果为:

name: zhangyangage: 23


以上,我们可以看出,在调用函数时没有age赋值,在输出结果时使用了函数定义时的默认值。那么如果我们对age赋值最后会输出什么呢?

def defaultparm(name,age=23):
    print('name:',name)
    print('age:',age)    
    return
defaultparm('zhangyang',24) #默认为23


输出结果:

name: zhangyangage: 24


通过执行函数我们看到,执行结果使用的是我们传入的参数。由此得知,当对默认参数传值时,函数执行调用是我们传入的值。
把默认参数放在前面是否可行?定义如下函数并执行:

def defaultparm(age=23,name):
    print('name:',name)
    print('age:',age)    
    return
defaultparm(name='zhangyang',age=24) 

SyntaxError: non-default argument follows default argument


执行结果是编译不通过,错误信息是非默认参数在默认参数后面了。
这里告诉我们非默认参数一定要放在默认参数后面。如果需要多个默认参数怎么办呢?
示例1:

def defaultparm1(age=23,name,addr='sichuan'):
    print('name:',name)
    print('age:',age)
    print('addr:',addr)    
    return
def defaultparm2(age=23,addr='sichuan',name):
    print('name:',name)
    print('age:',age)
    print('addr:',addr)    
    return
defaultparm1(age=23,'zhangyang',addr='sichuan')
defaultparm2(age=23,addr='sichuan','zhangyang')

SyntaxError: non-default argument follows default argument

示例2:

def defaultparm1(name,age=23,addr='sichuan'):    
    print('name:',name)
    print('age:',age)
    print('addr:',addr)
    return
print("传递必须参数")
defaultparm1('zhangyang')
print('传递必须参数,更改第一个默认参数')
defaultparm1('zhangyang',24)
print('传递必须参数,更改所有默认参数')
defaultparm1('zhangyang',24,'beijing')
print('传递必须参数,指定默认参数名并更改参数值')
defaultparm1('zhangyang',addr='beijing')
print('传递必须参数,指定参数名并更改参数值')
defaultparm1('zhangyang',addr='beijing',age=24)
print('第一个默认参数不带参数名,第二个带')
defaultparm1('zhangyang',24,addr='beijing')
print('两个默认参数都带参数名')
defaultparm1('zhangyang',age=24,addr='beijing')
print('第一个默认参数带,第二个不带,此处报错')
defaultparm1('zhangyang',age=24,'beijing')传递必须参数


输出结果:

name: zhangyang
age: 23
addr: sichuan
传递必须参数,更改第一个默认参数
name: zhangyang
age: 24
addr: sichuan
传递必须参数,更改所有默认参数
name: zhangyang
age: 24
addr: beijing
传递必须参数,指定默认参数名并更改参数值
name: zhangyang
age: 23
addr: beijing
传递必须参数,指定参数名并更改参数值
name: zhangyang
age: 24
addr: beijing
第一个默认参数不带参数名,第二个带
name: zhangyang
age: 24
addr: beijing
两个默认参数都带参数名
name: zhangyang
age: 24
addr: beijing

SyntaxError: positional argument follows keyword argument

结论:
1、无论有多少默认参数,默认参数都不能在必须参数之前。
2、无论有多少默认参数,若不传入默认参数值,则使用默认参数。
3、若要改变某一个默认参数值,又不想传入其他默认参数,且该默认参数的位置不是第一个,则可以通过参数名更改想要更改的默认参数值。
4、若有一个默认参数通过传入参数名更改参数值,则其他想要更改的默认参数都需要传入参数名更改参数值,否则报错。
5、更改默认参数值时,传入默认参数的顺序不需要根据定义的函数中的默认值参数的顺序传入,不过最好同时传入参数名,否则容易出现执行结果与预期不一致的情况。
通过以上示例我们可以看出,默认参数是比较有用的,通过默认参数我们可以少写代码。

1.4 可变参数

如果需要一个函数能够处理的参数声明时更过,这些参数叫做可变参数,和前两种参数不同,可变参数声明时不会命名。
基本语法如下:

def functionname([formal_args,]*var_args_tuple):
'函数__文档字符串'
function_suitereturn [expression]


加了*号的变量名会存放所有未命名的变量参数,如果变量参数在函数调用时没有指定参数,就是一个空元组,我们也可以不向可变函数传递未命名的变量。
例:

def personinfoi(arg,*vartuple):    
    print(arg)
    for var in vartuple:        
        print('我属于不定长参数部分',var)
    return
print('不带可变参数')
personinfoi('zhangyang')
print('带两个可变参数')
personinfoi('zhangyang','23','sichuan')
print('带五个可变参数')
personinfoi('zhangyang','23','sichuan',123,'test','beijing')


输出结果:

不带可变参数
zhangyang
带两个可变参数
zhangyang
我属于不定长参数部分 23
我属于不定长参数部分 sichuan
带五个可变参数
zhangyang
我属于不定长参数部分 23
我属于不定长参数部分 sichuan
我属于不定长参数部分 123
我属于不定长参数部分 test
我属于不定长参数部分 beijing

这段代码看起来不可思议,在定义函数时只定义了两个参数,调用时却可以传递那么多参数。
这其实就是可变参数的好处,我们在参数前面加上一个星号,在函数内部,参数前面的星号将所有值放在同一个元组中,通过这种方式将这些值收集起来,然后使用,参数vartuple接受的是一个元组,调用函数时可以传入任意个数的参数,也可以不传。
在这个示例中我们有用到for循环,通过for循环遍历元组。
通过这种方式定义函数,调用非常方便,因此我们会经常遇到,我们还可以通过以下方式来处理之前学习关键字参数,例如:

other={'城市':'beijing','爱好':'编程'}
def personinfo(name,num,**kw):
    print('名称:',name,'学号:',num,'其他:',kw)

personinfo('zhangyang','52',城市=other['城市'],爱好=other['爱好'])
#personinfo('zhangyang','52',**other)

输出结果:

    名称: zhangyang 学号: 52 其他: {'爱好': '编程', '城市': 'beijing'}

注意:**other表示把other这个字典所有的key-value用关键字参数传入到函数**kw参数,kw获得一个字典,注意kw获得的字典是other复制的,对kw的改动不会影响函数外的other。

1.5 组合参数

在python中定义函数可以是必须参数、关键字参数、默认参数和可变关键字参数,这四种可以组合使用,注意定义参数的顺序必须是必须参数、默认参数、可变参数和关键字参数。
接下来我们介绍组合参数的使用。示例:

 def exp(p1,p2,df=0,*vart,**kw):
     print('p1=',p1,'p2=',p2,'df=',df,'vart=',vart,'kw=',kw)
     
 exp(1,2)
 exp(1,2,c=3)
 exp(1,2,3,'a','b')
 exp(1,2,3,'abc',x=8,y=9)

输出结果:

p1= 1 p2= 2 df= 0 vart= () kw= {}
p1= 1 p2= 2 df= 0 vart= () kw= {'c': 3}
p1= 1 p2= 2 df= 3 vart= ('a', 'b') kw= {}
p1= 1 p2= 2 df= 3 vart= ('abc',) kw= {'y': 9, 'x': 8}

使用组合参数,python解释器会自动按照参数位置和参数名把对应的参数传递进去。
此处还可以用tuple和dict调用上述函数,使用方法如下:

args=(1,2,3,4)
kw={'x':8,'y':9}
exp(*args,**kw)

由上可知,任意函数都可以通过类似func(args,*kw)的形式调用,无论参数是如何定义的。

神回复

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。