Python程序设计开发宝典
上QQ阅读APP看书,第一时间看更新

3.5 序列解包的多种形式和用法

序列解包(Sequence Unpacking)是Python中非常重要和常用的一个功能,可以使用非常简洁的形式完成复杂的功能,提高了代码的可读性,减少了程序员的代码输入量。

        >>>x, y, z=1,2,3                              #多个变量同时赋值
        >>>v_tuple=(False,3.5, 'exp')
        >>>(x, y, z)=v_tuple
        >>>x, y, z=v_tuple
        >>>x, y, z=range(3)                           #可以对range对象进行序列解包
        >>>x, y, z=iter([1,2,3])                      #使用迭代器对象进行序列解包
        >>>x, y, z=map(str, range(3))                 #使用可迭代的map对象进行序列解包
        >>>a, b=b, a                                  #交换两个变量的值

序列解包还可以用于列表、字典、enumerate对象、filter对象、zip对象等。对字典使用时,默认是对字典“键”进行操作,如果对“键:值”对进行操作应使用字典的items()方法说明,如果需要对字典“值”进行操作应使用字典的values()方法明确指定。

        >>>a=[1,2,3]
        >>>b, c, d=a                         #列表也支持序列解包的用法
        >>>x, y, z=sorted([1,3,2])           #sorted()函数返回排序后的列表
        >>>s={'a':1, 'b':2, 'c':3}
        >>>b, c, d=s.items()                 #这里的重点是序列解包的用法
        >>>b
        ('c',3)
        >>>b, c, d=s                         #使用字典时不用太多考虑元素的顺序
        >>>b                                 #在Python 3.6.x和更新版本中略有不同是正常的
        'c'
        >>>b, c, d=s.values()
        >>>print(b, c, d)
        1 3 2
        >>>a, b, c='ABC'                     #字符串也支持序列解包
        >>>print(a, b, c)
        A B C

使用序列解包可以很方便地同时遍历多个序列。

        >>>keys=['a', 'b', 'c', 'd']
        >>>values=[1,2,3,4]
        >>>for k, v in zip(keys, values):
            print((k, v), end='')
        ('a',1) ('b',2) ('c',3) ('d',4)
        >>>x=['a', 'b', 'c']
        >>>for i, v in enumerate(x):
            print('The value on position{0}is{1}'.format(i, v))
        The value on position 0 is a
        The value on position 1 is b
        The value on position 2 is c
        >>>s={'a':1, 'b':2, 'c':3}
        >>>for k, v in s.items():            #字典中每个元素包含“键”和“值”两部分
            print((k, v), end='')
        ('a',1) ('b',2) ('c',3)

下面的代码演示了序列解包的另类用法和错误的用法:

        >>>print(*[1,2,3],4, *(5,6))
        1 2 3 4 5 6
        >>>*range(4),4
        (0,1,2,3,4) 
        >>>*range(4)                             #不允许这样用
        SyntaxError: can't use starred expression here
        >>>{*range(4),4, *(5,6,7)}
        {0,1,2,3,4,5,6,7}
        >>>{'x': 1, **{'y': 2}}
        {'y': 2, 'x': 1}
        >>>a, b, c=range(3)
        >>>a, b, c=*range(3)                     #不允许这样用
        SyntaxError: can't use starred expression here
        >>>a, b, c, d=*range(3),3

下面的代码看起来与序列解包类似,但严格来说是序列解包的逆运算,与函数的可变长度参数一样(详见5.2.4节),用来收集等号右侧的多个数值。

      >>>a, *b, c=1,2,3,4,5
      >>>a, b, c
      (1, [2,3,4],5)
      >>>b
      [2,3,4]
      >>>a, *b, c=1,2,3,4
      >>>a, b, c
      (1, [2,3],4)
      >>>a, *b, c=tuple(range(20))
      >>>b
      [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18]
      >>>*b=1,2,3,4                         #等号左侧必须为列表、元组或多个变量
      SyntaxError: starred assignment target must be in a list or tuple