目录
一、作为函数的可变参数标志以及参数解包
二、赋值语句中作为可变变量标志
三、在除函数参数语境外的其他语境下对可迭代对象进行解包
星号在python中的用法主要可分为三类:一是作为函数的可变参数标志以及在函数参数的语境下对可迭代对象进行解包并进行参数传递(参数解包),二是作为赋值语句中的可变变量标志,三是在非函数参数的其他特定的语境中直接对可迭代对象进行解包操作。这三种用法是在不同的python版本中不断的添加进去的,其中后两种用法只在3.x版本中可以使用,具体的讲,用法一是在2.x和3.x都可以使用的,第二种用法是在3.0版本添加进去的,第三种用法是在3.5版本中添加进去的,所以在使用星号的不同用法时,还需要注意python的版本,以免出错。下面对每种用法进行详细的说明。
一、作为函数的可变参数标志以及参数解包
在函数的参数中,当以*标记一个参数时,表明这个参数是可变参数,具体来讲,用单星号*标记参数,表示其是可变的位置参数,并且以元组的形式将外部的多个位置参数返回给该参数变量,如果用双星号**标记,表示其看是可变的关键词参数,并且会以字典的形式将外部的多组关键词参数和值返回给该参数变量。如下所示。
def f1(a,*b,**c):
print(a)
print(b)
print(c)
f1(1,2,(3,4),k1=5,k2=6)
# output:
# 1
# (2,(3,4))
# {'k1':5,'k2':6}
此外,如果我们要将一个可迭代对象作为参数传给一个函数,在这种语境下,可以直接利用*iterable语法对可迭代对象解包,并把解包后的内容传给函数,如下所示。要注意的是,如果解包之后的元素个数不和函数位置参数的个数相等的话,是会抛出异常的,所以一般情况下,不建议在不含可变参数的函数中使用这种传参方式。
def f2(a,b):
print(a)
print(b)
f2(*[1,2])
# output:
# 1
# 2
f2(*[1,2,3]) # TypeError: f2() takes 2 positional argument but 3 were given
def f3(a,*b):
print(a)
print(b)
f3(*(1,2,3))
# output:
# 1
# (2,3)
二、赋值语句中作为可变变量标志
当我们想要对一个可迭代对象进行拆分,并赋值给相应的变量时,我们可以用星号标记某个变量,这个变量表示可变变量,意思表示其内容是不定的,内容根据其他的变量的个数决定。因为其原理就是优先赋值给其他确定的变量,然后剩下的内容再赋值给可变变量,实际上,可变变量的内容就是对可迭代对象剩下内容解包后得到的内容,并以列表list对象返回给变量,如下所示。
a,*b=(1,2,3,4,5)
*c,d=range(5)
print(a) # output: 1
print(b) # output: [2,3,4,5]
print(c) # output: [0,1,2,3]
print(d) # output: 4
三、在除函数参数语境外的其他语境下对可迭代对象进行解包
在3.5版本开始,python对星号增加新的适用场景,即在元组、列表、集合和字典内部进行对可迭代参数直接解包,这里需要一再强调的是,这里是在上述四个场景下才可以对可迭代参数直接解包,在其他场景下进行可迭代对象的星号解包操作时不允许的,如下所示。
a=*range(3),
b=*range(3),3
c=[*range(3)]
d={*range(3)}
e={**{'y':1}}
print(a) # output: (0,1,2)
print(b) # output: (0,1,2,3)
print(c) # output: [0,1,2]
print(d) # output: {0,1,2}
print(e) # output: {'y':1}
还要注意的是,由于这里只能在这些指定的场景下对可迭代对象直接解包,如果直接*range(3)是会报错的,要区别于上述的第一条语句,注意上述第一条语句中*range(3)后面是有逗号的,所以这就表示在元组的场景下进行解包,所以是允许的。