*args和**kwargs:
这一节我们要讨论Python里*和**的特殊含义,它们都和函数有关但是在函数调用时和函数声明时却有着不同的行为。
一般说来,无论是函数调用还是声明,单个星号表示有元组(或是列表)“出现”
而两个星号则代表附近有字典出没
函数调用里的*和**
我们来重新看一下之前的例子check_web_server函数,下面是函数的签名:
def check_web_server(host,port,path):
用check_web_server('127.0.0.1',8000,'/admin/')即可调用这个函数,那要是这些信息在一个三元组里的话怎么办?
host_info=('wwww.python.org',80,'/')
print host_info[0]
print host_info[1]
print host_info[2]
C:Python27python.exe C:/Users/TLCB/PycharmProjects/untitled/mycompany/Django/a3.py
wwww.python.org
80
/
host_info=('wwww.python.org',80,'/')
def check_web_server(host,port,path):
print 'host',host
print 'port',+port
print 'path',path
check_web_server(host_info[0],host_info[1],host_info[2])
C:Python27python.exe C:/Users/TLCB/PycharmProjects/untitled/mycompany/Django/a3.py
host wwww.python.org
port 80
path /
然后这种写法既不可扩展(要是函数有超过一打的参数怎么办?)也不好看,这时单星号就可以解决我们的问题,
因为当调用函数时,表达式在计算一个带星号前缀的元组或列表时会将其"打开".
所以下面的例子和上面的代码是等价的:
host_info=('wwww.python.org',80,'/')
def check_web_server(host,port,path):
print 'host',host
print 'port',+port
print 'path',path
check_web_server(*host_info)
C:Python27python.exe C:/Users/TLCB/PycharmProjects/untitled/mycompany/Django/a3.py
host wwww.python.org
port 80
path /
这样的写法就明显要干净和优雅得多
而双信号对字典的用法也是类似的,现在我们来创建一个具有和('www.python.org',80,'/')相似的字典:
host_info={'host':'wwww.python.org','port':80,'path':'/'}
def check_web_server(host,port,path):
print 'host',host
print 'port',+port
print 'path',path
check_web_server(**host_info)
C:Python27python.exe C:/Users/TLCB/PycharmProjects/untitled/mycompany/Django/a3.py
host wwww.python.org
port 80
path /
函数签名里的*和** 虽然看着相似但作用却完全不同:它们让Python得以支持变长参数,
有时也称为"varargs".即函数可以接受任何数量的参数:
def daily_sales_total(*all_sales):
total =0
for each_sale in all_sales:
total +=each_sale
return total
print daily_sales_total()
C:Python27python.exe C:/Users/TLCB/PycharmProjects/untitled/mycompany/Django/a5.py
0
def daily_sales_total(*all_sales):
total =0
for each_sale in all_sales:
total +=each_sale
return total
print daily_sales_total(1,3,5)
C:Python27python.exe C:/Users/TLCB/PycharmProjects/untitled/mycompany/Django/a5.py
9
不管你向这个函数传递多少参数,它都能够处理。all_salves就是一个包含了所有参数的元组
你还可以把普通参数和变长参数混在一起使用,这时vararg就会捕获所有剩下的参数,
例如在这个假设的check_web_server函数定义就能接受额外的参数了。
注意:
在函数定义里使用变长参数时,所有必须出现的参数一定先出现,然后是默认值的参数,最后才是变成参数。
def check_web_server(host,port,path,*args):
print 'host',host
print 'port',port
print 'path',path
for s in args:
print s
check_web_server('192.168.137.2','80','/app',3,4,5,6,7)
C:Python27python.exe C:/Users/TLCB/PycharmProjects/untitled/mycompany/Django/a5.py
host 192.168.137.2
port 80
path /app
3
4
5
6
7
类似地,你也可以在函数签名里用双星号来接受任意数目的关键字参数,它们会在函数被调用的时候
导入到一个字典里去。
def check_web_server(host,port,path,*args,**kwargs):
print 'host',host
print 'port',port
print 'path',path
for s in args:
print s
print '---------------'
print 'xx',kwargs['xx']
print 'yy', kwargs['yy']
print 'zz', kwargs['zz']
check_web_server('192.168.137.2','80','/app',3,4,5,6,7,xx='wwww.python.org',yy='80',zz='/')
C:Python27python.exe C:/Users/TLCB/PycharmProjects/untitled/mycompany/Django/a5.py
host 192.168.137.2
port 80
path /app
3
4
5
6
7
---------------
xx wwww.python.org
yy 80
zz /
Process finished with exit code 0
实际上,还有一种全部由变长参数组成的所谓"通用"Python方法签名
def f(*args,**kwargs):
for s in args:
print s
print '---------------'
print kwargs['x']
f('1','2','aa',x='ff',y='gg')
C:Python27python.exe C:/Users/TLCB/PycharmProjects/untitled/mycompany/Django/a6.py
1
2
aa
---------------
ff
def f(*args,**kwargs):
for s in args:
print s
print '---------------'
print kwargs['x']
print kwargs['y']
f('1','2','aa',x='ff',y='gg')
C:Python27python.exe C:/Users/TLCB/PycharmProjects/untitled/mycompany/Django/a6.py
1
2
aa
---------------
ff
gg
def f(*args,**kwargs):
for s in args:
print s
print '---------------'
print kwargs['x']
print kwargs['y']
f('1','2','aa',x='ff',y='gg',z)
C:Python27python.exe C:/Users/TLCB/PycharmProjects/untitled/mycompany/Django/a6.py
File "C:/Users/TLCB/PycharmProjects/untitled/mycompany/Django/a6.py", line 7
f('1','2','aa',x='ff',y='gg',z)
SyntaxError: non-keyword arg after keyword arg