《Think Python 2e》学习精粹(十二):元组

《Think Python 2e》学习精粹(十二):元组



  • 元组是一组值的序列,是一种内置数据类型;

1、元组是不可变的

  • 元组中的值可以是任意类型, 使用整数索引;

  • 元组中的值用逗号隔开,元组通常用括号括起来,创建单一元素元组时,需要在结尾处添加一个逗号;

    >>> t1 = 'a', 'b', 'c', 'd', 'e'
    >>> t2 = ('a', 'b', 'c', 'd', 'e')
    >>> t3 = 'a',
    
  • 另一个创建元组的方法是使用内建函数 tuple

    • 在没有参数传递时,创建一个空元组;

      >>> t = tuple()
      >>> t
      ()
      
    • 如果实参是一个序列(字符串、列表或者元组),结果将是一个包含序列内元素的元组;

      >>> t = tuple('lupins')
      >>> t
      ('l', 'u', 'p', 'i', 'n', 's')
      
    • 因为 tuple 是内建函数名,所以应该避免将它用作变量名;

  • 列表的大多数操作符同样也适用于元组;

    • 方括号运算符将索引一个元素;
    • 切片运算符选取一个范围内的元素;
  • 元组是不可变的,元组的元素(item)不能更新;

    >>> t = ('a', 'b', 'c', 'd', 'e')
    >>> t[0]
    'a'
    >>> t[1:3]
    ('b', 'c')
    >>> t[0] = 'A'
    TypeError: object doesn't support item assignment
    
  • 可以使用其他元组替换现有元组;

    >>> t = ('A',) + t[1:]
    >>> t
    ('A', 'b', 'c', 'd', 'e')
    
  • 关系型运算符也适用于元组和其他序列, Python 会首先比较序列中的第一个元素,如果它们相等,就继续比较下一组元素,以此类推,直至比值不同,其后的元素(即便是差异很大)也不会再参与比较;

    >>> (0, 1, 2) < (0, 3, 4)
    True
    >>> (0, 1, 2000000) < (0, 3, 4)
    True
    

2、元组赋值

  • 可以同时为元组中的一组变量赋值,左侧的变量数和右侧值的数目必须相同,一般来说,右侧可以是任意类型(字符串、列表或者元组)的序列;

    >>> a, b = b, a
    >>> a, b = 1, 2, 3
    ValueError: too many values to unpack
    >>> addr = 'monty@python.org'
    >>> uname, domain = addr.split('@')
    >>> uname
    'monty'
    >>> domain
    'python.org'
    

    split 函数返回的对象是一个包含两个元素的列表;

3、元组作为返回值

  • 严格地说,一个函数只能返回一个值(包括元组),其效果等同于返回多个值;

    >>> t = divmod(7, 3)
    >>> t
    (2, 1)
    

4、可变长度参数元组

  • 函数可以接受可变数量的参数, 以 “*” 开头的形参将输入的参数 汇集 到一个元组中,汇集形参可以使用任意名字,但是习惯使用 args
  • 与汇集相对的,是 分散(scatter) , 如果你有一个值序列,并且希望将其作为多个参数传递给一个函数, 可以使用运算符*;

5、列表和元组

  • zip是一个内建函数,可以接受将两个或多个序列组(字符串、列表、元组等),并返回一个元组列表, 其中每个元组包含了各个序列中相对位置的一个元素;

    >>> s = 'abc'
    >>> t = [0, 1, 2]
    >>> zip(s, t)
    <zip object at 0x7f7d0a9e7c48>
    >>> for pair in zip(s, t):
    ...     print(pair)
    ...
    ('a', 0)
    ('b', 1)
    ('c', 2)
    
  • zip对象是迭代器的一种,即任何能够按照某个序列迭代的对象, 迭代器在某些方面与列表非常相似,但不同之处在于,无法通过索引来选择迭代器中的某个元素;

  • 为了使用列表操作符和方法,你可以用 zip 对象创建一个列表,如果用于创建的序列长度不一,返回对象的长度以最短序列的长度为准;

    >>> list(zip(s, t))
    [('a', 0), ('b', 1), ('c', 2)]
    >>> list(zip('Anne', 'Elk'))
    [('A', 'E'), ('n', 'l'), ('n', 'k')]
    
  • 可以在 for 循环中使用元组赋值,遍历包含元组的列表;

    t = [('a', 0), ('b', 1), ('c', 2)]
    for letter, number in t:
        print(number, letter)
    
  • 如果将 zipfor 循环和元组赋值结合起来使用,你会得到一个可以同时遍历两个(甚至多个)序列的惯用法;

6、字典和元组

  • 字典有一个叫做 items 的方法,其结果是一个 dict_items 对象,它返回由多个元组组成的序列,其中每个元组是一个键值对;

  • dict_items 对象,这是一个对键值对进行迭代的迭代器,可以在 for 循环中使用它,由于是字典生成的对象,这些项是无序的;

    >>> d = {'a':0, 'b':1, 'c':2}
    >>> t = d.items()
    >>> t
    dict_items([('c', 2), ('a', 0), ('b', 1)])
    >>> for key, value in d.items():
    ...     print(key, value)
    ...
    c 2
    a 0
    b 1
    
  • 可以使用元组的列表初始化一个新的字典;

    >>> t = [('a', 0), ('c', 2), ('b', 1)]
    >>> d = dict(t)
    >>> d
    {'a': 0, 'c': 2, 'b': 1}
    
  • dictzip 结合使用,可以很简洁地创建一个字典;

    >>> d = dict(zip('abc', range(3)))
    >>> d
    {'a': 0, 'c': 2, 'b': 1}
    
  • 字典的 update 方法也接受元组列表,并将其作为键值对添加到已有的字典中去;

  • 在字典中使用元组作为键(主要因为无法使用列表)的做法很常见;

7、序列嵌套

  • 在很多情况下,不同类型的序列(字符串、列表、元组)可以互换使用;
  • 字符串比其他序列的限制更多,因为它的所有元素都必须是字符,且字符串不可变,如果你希望能够改变字符串中的字符,使用列表嵌套字符或许更合适;
  • 列表比元组更常用,主要是因为它们是可变的,但是有些情况下,更倾向于使用元组;
    • 在一些情况下(例如 return 语句),从句式上生成一个元组比列表要简单;
    • 如果使用一个序列作为字典的键,那么你必须使用元组或字符串这样的不可变类型;
    • 如果向函数传入一个序列作为参数,那么使用元组可以降低由于别名而产生的意外行为的可能性;
    • 由于元组的不可变性,它们没有类似(sort) 和 (reverse)这样修改现有列表的方法, Python 提供了内建函数 sortedreversed ,前者可以接受任意序列,并返回一个正序排列的新列表,后者则接受一个序列,返回一个可逆序迭代列表的迭代器;

8、调试

  • 列表、字典和元组都是数据结构data structures);
  • 复合数据结构(compound data structures):列表嵌套元组,以及使用元组作为键、列表作为值的字典;
  • 复合数据结构非常实用,但是使用时容易出现所谓的形状错误(shape errors),也就是由于数据结构的类型、大小或结构问题而引发的错误;
  • 可以从 http://thinkpython2.com/code/structshape.py 下载 structshape 模块,它提供了一个同名函数,可以接受任意类型的数据结构作为实参,然后返回一个描述它形状的字符串,在追踪数据结构的类型上遇到了困难,可以使用 structshape 来帮助分析。

(本篇起,学习精粹和作业实现系列均为用 Typora 离线编辑,格式会有差异)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值