可迭代对象解包操作
我们可以使用星号==*==来解包可迭代对象,这将使我们的程序更加清晰且优雅。
例如,如果我们要将不同的可迭代对象(例如一个列表,一个元组和一个集合)组合成一个新列表,哪种方法最好?
显然,我们可以使用 for 循环来迭代所有元素并将它们逐一添加到新列表中,样例代码如下:
A = [1, 2, 3]
B = (4, 5, 6)
C = {7, 8, 9}
L = []
for a in A:
L.append(a)
for b in B:
L.append(b)
for c in C:
L.append(c)
print(L)
# [1, 2, 3, 4, 5, 6, 8, 9, 7]
上述实现方式虽然可以完成我们的目的,但是代码看起来太冗长了,而且不是很Pythonic 。
推荐的改进方式是使用列表生成式,如下所示:
A = [1, 2, 3]
B = (4, 5, 6)
C = {7, 8, 9}
L = [a for a in A] + [b for b in B] + [c for c in C]
print(L)
# [1, 2, 3, 4, 5, 6, 8, 9, 7]
上述代码中,我们将三个 for 循环减少为一行列表生成式。它已经是Pythonic了,但不一定是最简单的!
是时候看看星号的强大之处啦
A = [1, 2, 3]
B = (4, 5, 6)
C = {7, 8, 9}
L = [*A, *B, *C]
print(L)
# [1, 2, 3, 4, 5, 6, 8, 9, 7]
也可以用这种机制来给函数传入参数,给类实例化对象
args=[3, 32, 6, 2, 2]
class Conv(nn.Module):
# Standard convolution
def __init__(self, c1, c2, k=1, s=1, p=None, g=1, act=True): # ch_in, ch_out, kernel, stride, padding, groups
super().__init__()
self.conv = nn.Conv2d(c1, c2, k, s, autopad(k, p), groups=g, bias=False)
self.bn = nn.BatchNorm2d(c2)
self.act = nn.SiLU() if act is True else (act if isinstance(act, nn.Module) else nn.Identity())
def forward(self, x):
return self.act(self.bn(self.conv(x)))
def forward_fuse(self, x):
return self.act(self.conv(x))
conv=Conv(*args)#实例化对象,c1, c2, k, s, p分别等于3, 32, 6, 2, 2
如果我们利用一个*作为dict 的前缀,它的key 将被解包;如果我们使用双星号** 作为前缀,其value 将被解包;此时我们必须显示使用key 来接收解包后的value 。
D = {'first': 1, 'second': 2, 'third': 3}
print(*D)
# first second third
# print(**D)
# TypeError: 'first' is an invalid keyword argument for print()
print('{first},{second},{third}'.format(**D))
# 1,2,3
扩展可迭代对象解包
解包的语法可以让我们的代码更加简洁,样例如下:
L = [1, 2, 3, 4, 5, 6, 7, 8]
a, *b = L
print(a)
# 1
print(b)
# [2, 3, 4, 5, 6, 7, 8]