Python-列表和元组

1.概述

数据结构是以某种方式组合起来的数据元素(如数字、字符乃至其他数据结构)集合。在Python中,最基本的序列(sequence)数据结构为列表(list)和元组(tuple)。列表中的每个元素都有编号,即位置或索引,其中第一个元素的索引为0,第二个元素的索引为1,依次类推,同时列表中也可以嵌套列表,形成更复杂的数据结构。元组是一种特殊的序列,类似于列表,只是不能修改。

2.列表

2.1.列表数据类型

”列表“是一个值,包含多个字构成的序列。”列表值“指的是列表本身(作为一个值,可以保存在变量中,或传递给函数,像所有其他值一样),而不是指列表之内的那些值。列表用左方括号开始,用右方括号结束,即[]。列表中的值也称为”表项“,表项用逗号分隔。

    >>> [1, 2, 3]
    [1, 2, 3]
    >>> ['cat', 'bat', 'rat', 'elephant']
    ['cat', 'bat', 'rat', 'elephant']
    >>> ['hello', 3.1415, True, None, 42]
    ['hello', 3.1415, True, None, 42]>>> spam = ['cat', 'bat', 'rat', 'elephant']
    >>> spam
    ['cat', 'bat', 'rat', 'elephant']
2.1.1.用下标取得列表成员的值

可用下表索引列表中的值,假定列表['cat', 'bat', 'rat', 'elephant']保存在spam中,spam[0]的值为catspam[1]的值为bat,依次类推。

    >>> spam = ['cat', 'bat', 'rat', 'elephant']
    >>> spam[0]
    'cat'
    >>> spam[1]
    'bat'
    >>> spam[2]
    'rat'
    >>> spam[3]
    'elephant'
    >>> ['cat', 'bat', 'rat', 'elephant'][3]
    'elephant'
    >>> 'Hello ' + spam[0]
    'Hello cat'
    >>> 'The ' + spam[1] + ' ate the ' + spam[0] + '.'
    'The bat ate the cat.'

如果使用的下标超出了列表中值的个数,Python将给出IndexError出错信息。

    >>> spam = ['cat', 'bat', 'rat', 'elephant']
    >>> spam[10000]
    Traceback (most recent call last):
    File "<pyshell#9>", line 1, in <module>
    spam[10000]
    IndexError: list index out of range

下标只能是整数,不能是浮点值。下面的例子将导致TypeError错误。

    >>> spam = ['cat', 'bat', 'rat', 'elephant']
    >>> spam[1]
    'bat'
    >>> spam[1.0]
    Traceback (most recent call last):
    File "<pyshell#13>", line 1, in <module>
    spam[1.0]
    TypeError: list indices must be integers, not float
    >>> spam[int(1.0)]
    'bat'

列表也可以包含其他列表值。这些嵌套列表中的值,可以通过多重下标来访问。第一个下标表明使用哪个列表值,第二个下标表明该列表值中的值。如果只使用一个下标,程序将打印出该下标处的完整列表值。

    >>> spam = [['cat', 'bat'], [10, 20, 30, 40, 50]]
    >>> spam[0]
    ['cat', 'bat']
    >>> spam[0][1]
    'bat'
    >>> spam[1][4]
    50
2.1.2.负数下标

虽然下标从0开始并向上增长,但也可以用负整数作为下标。整数值−1指的是列表中的最后一个下标,−2指的是列表中倒数第二个下标,依次类推。

    >>> spam = ['cat', 'bat', 'rat', 'elephant']
    >>> spam[-1]
    'elephant'
    >>> spam[-3]
    'bat'
    >>> 'The ' + spam[-1] + ' is afraid of the ' + spam[-3] + '.'
    'The elephant is afraid of the bat.'
2.1.3.利用切片取得子列表

就像下标可以从列表中取得单个值一样,“切片”可以从列表中取得多个值,结果是一个新的列表。切片输入在一对方括号中,但有两个冒号分隔的整数。在一个切片中,第一个整数是切片开始处的下标,第二个整数是切片结束处的下标。切片向上增长,直至第二个下标的值,但不包括他。

    >>> spam = ['cat', 'bat', 'rat', 'elephant']
    >>> spam[0:4]
    ['cat', 'bat', 'rat', 'elephant']
    >>> spam[1:3]
    ['bat', 'rat']
    >>> spam[0:-1]
    ['cat', 'bat', 'rat']

省略第一个下标相当于使用0,或列表的开始。省略第二个下标相当于使用列表的长度,意味着分片直至列表的末尾。

    >>> spam = ['cat', 'bat', 'rat', 'elephant']
    >>> spam[:2]
    ['cat', 'bat']
    >>> spam[1:]
    ['bat', 'rat', 'elephant']
    >>> spam[:]
    ['cat', 'bat', 'rat', 'elephant']
2.1.4.列表长度

len()函数将返回传递给它的列表中值的个数,就像它能计算字符串中字符的个数一样。

    >>> spam = ['cat', 'dog', 'moose']
    >>> len(spam)
    3
2.1.5.用下标改变列表中的值

一般情况下,赋值语句左边是一个变量名,就像spam = 4。但是,也可以使用列表的下标来改变下标处的值。例如,spam[1] = 'aardvark'意味着将列表spam下标1处的值赋值为字符串'aardvark'

    >>> spam = ['cat', 'bat', 'rat', 'elephant']
    >>> spam[1] = 'aardvark'
    >>> spam
    ['cat', 'aardvark', 'rat', 'elephant']
    >>> spam[2] = spam[1]
    >>> spam
    ['cat', 'aardvark', 'aardvark', 'elephant']
    >>> spam[-1] = 12345
    >>> spam
    ['cat', 'aardvark', 'aardvark', 12345]
2.1.6.列表的连接与列表的复制

+操作符可以连接两个列表,得到一个新列表,就像它将两个字符串合并成一个新字符串一样。*操作符可以用于一个列表和一个整数,实现列表的复制。

    >>> [1, 2, 3] + ['A', 'B', 'C']
    [1, 2, 3, 'A', 'B', 'C']
    >>> ['X', 'Y', 'Z'] * 3
    ['X', 'Y', 'Z', 'X', 'Y', 'Z', 'X', 'Y', 'Z']
    >>> spam = [1, 2, 3]
    >>> spam = spam + ['A', 'B', 'C']
    >>> spam
    [1, 2, 3, 'A', 'B', 'C']
2.1.7.删除列表中的值

del语句将删除列表中下标处的值,表中被删除值后面的所有值,都将向前移动一个下标。

    >>> spam = ['cat', 'bat', 'rat', 'elephant']
    >>> del spam[2]
    >>> spam
    ['cat', 'bat', 'elephant']
    >>> del spam[2]
    >>> spam
    ['cat', 'bat']

del语句也可用于一个简单变量,删除它,作用就像是“取消赋值”语句。如果在删除之后试图使用该变量,就会遇到NameError错误,因为该变量已不再存在。在实践中,你几乎永远不需要删除简单变量。del语句几乎总是用于删除列表中的值。

2.2.使用列表
2.2.1.遍历列表

遍历列表有4种方法,常用的是第1种和第2种。

    spam = ['cat', 'bat', 'rat', 'elephant']
    # 使用range和列表长度进行遍历
    for i in range(len(spam)):
        print(spam[i])
    输出:
        cat
        bat
        rat
        elephant    

    # 利用列表本身进行遍历
    for i in spam:
        print(i)
    输出:
        cat
        bat
        rat
        elephant 

    # 使用迭代器遍历列表
    for i in iter(spam):
        print(i)
    输出:
        cat
        bat
        rat
        elephant 

    # 使用函数enumerate遍历列表,输出的结果是一个元组,包含元素的下标和值
    for i in enumerate(spam):
        print(i)
    输出:
        (0, 'cat')
        (1, 'bat')
        (2, 'rat')
        (3, 'elephant')
2.2.2.in和not in操作符

利用innot in操作符,可以确定一个值是否在列表中。这些表达式将求值为布尔值。

    >>> 'howdy' in ['hello', 'hi', 'howdy', 'heyas']
    True
    >>> spam = ['hello', 'hi', 'howdy', 'heyas']
    >>> 'cat' in spam
    False
    >>> 'howdy' not in spam
    False
    >>> 'cat' not in spam
    True
2.2.3.多重赋值

多重赋值技巧是一种快捷方式,让你在一行代码中,用列表中的值为多个变量赋值。所以不必像下面这样。

    >>> cat = ['fat', 'black', 'loud']
    >>> size = cat[0]
    >>> color = cat[1]
    >>> disposition = cat[2]

而是输入下面的代码。

    >>> cat = ['fat', 'black', 'loud']
    >>> size, color, disposition = cat
    >>> cat
    ['fat', 'black', 'loud']

变量的数目和列表的长度必须严格相等,否则Python将给出ValueError错误。

    >>> cat = ['fat', 'black', 'loud']
    >>> size, color, disposition, name = cat
    Traceback (most recent call last):
    File "<pyshell#84>", line 1, in <module>
    size, color, disposition, name = cat
    ValueError: need more than 3 values to unpack
2.3.列表的方法

列表有一组方法,可以进行查找、添加、删除或操作列表中的值。

2.3.1.查找

列表值有一个index()方法,可以传入一个值,如果该值存在于列表中,就返回它的下标。如果该值不在列表中,Python就报ValueError

    >>> spam = ['hello', 'hi', 'howdy', 'heyas']
    >>> spam.index('hello')
    0
    >>> spam.index('heyas')
    3
    >>> spam.index('howdy howdy howdy')
    Traceback (most recent call last):
    File "<pyshell#31>", line 1, in <module>
    spam.index('howdy howdy howdy')
    ValueError: 'howdy howdy howdy' is not in list

如果列表中存在重复的值,就返回它第一次出现的下标。

    >>> spam = ['Zophie', 'Pooka', 'Fat-tail', 'Pooka']
    >>> spam.index('Pooka')
    1
2.3.2.追加和插入

使用append()方法可以向列表末尾追加新值,该方法的返回值是None

    >>> spam = ['cat', 'dog', 'bat']
    >>> spam.append('moose')
    >>> spam
    ['cat', 'dog', 'bat', 'moose']

insert()方法可以在列表任意下标处插入一个值。insert()方法的第一个参数是新值的下标,第二个参数是要插入的新值,该方法的返回值是None

    >>> spam = ['cat', 'dog', 'bat']
    >>> spam.insert(1, 'chicken')
    >>> spam
    ['cat', 'chicken', 'dog', 'bat']

append()insert()方法是列表方法,只能在列表上调用,不能在其他值上调用。若在字符串和整型上调用将产生AttributeError错误信息。

    >>> eggs = 'hello'
    >>> eggs.append('world')
    Traceback (most recent call last):
    File "<pyshell#19>", line 1, in <module>
    eggs.append('world')
    AttributeError: 'str' object has no attribute 'append'
    >>> bacon = 42
    >>> bacon.insert(1, 'world')
    Traceback (most recent call last):
    File "<pyshell#22>", line 1, in <module>
    bacon.insert(1, 'world')
    AttributeError: 'int' object has no attribute 'insert'
2.3.3.删除

remove()方法会删除列表中的元素。

    >>> spam = ['cat', 'bat', 'rat', 'elephant']
    >>> spam.remove('bat')
    >>> spam
    ['cat', 'rat', 'elephant']

试图删除列表中不存在的值,将导致ValueError错误。

    >>> spam = ['cat', 'bat', 'rat', 'elephant']
    >>> spam.remove('chicken')
    Traceback (most recent call last):
    File "<pyshell#11>", line 1, in <module>
    spam.remove('chicken')
    ValueError: list.remove(x): x not in list

如果该值在列表中出现多次,只有第一次出现的值会被删除。

    >>> spam = ['cat', 'bat', 'rat', 'cat', 'hat', 'cat']
    >>> spam.remove('cat')
    >>> spam
    ['bat', 'rat', 'cat', 'hat', 'cat']

如果知道想要删除的值在列表中的下标,del语句就很好用。如果知道想要从列表中删除的值,remove()方法就很好用。

2.3.4.排序

数值列表或字符串列表,可用sort()方法排序。

    >>> spam = [2, 5, 3.14, 1, -7]
    >>> spam.sort()
    >>> spam
    [-7, 1, 2, 3.14, 5]
    >>> spam = ['ants', 'cats', 'dogs', 'badgers', 'elephants']
    >>> spam.sort()
    >>> spam
    ['ants', 'badgers', 'cats', 'dogs', 'elephants']

也可以指定reverse关键字参数为True,让sort()按逆序排序。

    >>> spam.sort(reverse=True)
    >>> spam
    ['elephants', 'dogs', 'cats', 'badgers', 'ants']

使用sort()时应该注意一下三点。
(1)sort()方法当场对列表排序,返回值为None,不要试图记录返回值。
(2)不能对既有数字又有字符串值的列表排序,因为Python不知道如何比较它们。

    >>> spam = [1, 3, 2, 4, 'Alice', 'Bob']
    >>> spam.sort()
    Traceback (most recent call last):
    File "<pyshell#70>", line 1, in <module>
    spam.sort()
    TypeError: unorderable types: str() < int()

(3)sort()方法对字符串排序时,使用“ASCII 字符顺序”,而不是实际的字典顺序。这意味着大写字母排在小写字母之前。

    >>> spam = ['Alice', 'ants', 'Bob', 'badgers', 'Carol', 'cats']
    >>> spam.sort()
    >>> spam
    ['Alice', 'Bob', 'Carol', 'ants', 'badgers', 'cats']

如果需要按照普通的字典顺序来排序,就在sort()方法调用时,将关键字参数key设置为str.lower。这将导致sort()方法将列表中所有的表项当成小写,但实际上并不会改变它们在列表中的值。

    >>> spam = ['a', 'z', 'A', 'Z']
    >>> spam.sort(key=str.lower)
    >>> spam
    ['a', 'A', 'z', 'Z']

3.字符串

字符串也是表示序列的一种数据类型。字符串和列表实际上很相似,只是字符串是单个文本字符的列表。对列表的许多操作,也可以作用于字符串:按下标取值、切片、用于for循环、用于len(),以及用于innot in操作符。

    >>> name = 'Zophie'
    >>> name[0]
    'Z'
    >>> name[-2]
    'i'
    >>> name[0:4]
    'Zoph'
    >>> 'Zo' in name
    True
    >>> 'z' in name
    False
    >>> 'p' not in name
    False
    >>> for i in name:
    print('* * * ' + i + ' * * *')
    * * * Z * * *
    * * * o * * *
    * * * p * * *
    * * * h * * *
    * * * i * * *
    * * * e * * *

列表和字符串在一个重要的方面是不同的。列表是“可变的”数据类型,列表的值可以添加、删除或改变。但是字符串是“不可变的”,它不能被更改。尝试对字符串中的一个字符重新赋值,将导致TypeError错误。

    >>> name = 'Zophie a cat'
    >>> name[7] = 'the'
    Traceback (most recent call last):
    File "<pyshell#50>", line 1, in <module>
    name[7] = 'the'
    TypeError: 'str' object does not support item assignment

“改变”一个字符串的正确方式,是使用切片和连接。构造一个“新的”字符串,然后从老的字符串那里复制一些部分。

    >>> name = 'Zophie a cat'
    >>> newName = name[0:7] + 'the' + name[8:12]
    >>> name
    'Zophie a cat'
    >>> newName
    'Zophie the cat'

4.元组

元组(tuple)的数据类型和列表的数据类型很相似,但有两点不同,第一元组用圆括号(),而不是用方括号[],第二元组和字符串一样,是不可变的数据类型,不能添加、修改或删除,若更改元组,会输出TypeError错误信息。

    >>> eggs = ('hello', 42, 0.5)
    >>> eggs[0]
    'hello'
    >>> eggs[1:3]
    (42, 0.5)
    >>> len(eggs)
    3
    >>> eggs = ('hello', 42, 0.5)
    >>> eggs[1] = 99
    Traceback (most recent call last):
    File "<pyshell#5>", line 1, in <module>
    eggs[1] = 99
    TypeError: 'tuple' object does not support item assignment

如果元组中只有一个值,你可以在括号内该值的后面跟上一个逗号,表明这种情况。否则,Python将认为只是在一个普通括号内输入了一个值。逗号告诉Python,这是一个元组。

    >>> type(('hello',))
    <class 'tuple'>
    >>> type(('hello'))
    <class 'str'>

正如str(42)将返回42,即整数42的字符串表示形式,函数list()tuple()将返回传递给它们的值的列表和元组版本。

    >>> tuple(['cat', 'dog', 5])
    ('cat', 'dog', 5)
    >>> list(('cat', 'dog', 5))
    ['cat', 'dog', 5]
    >>> list('hello')
    ['h', 'e', 'l', 'l', 'o']

5.引用

将列表赋给一个变量时,实际上是将列表的“引用”赋给了该变量。引用是一个值,指向某些数据。列表引用是指向一个列表的值。

    >>> spam = [0, 1, 2, 3, 4, 5]
    >>> cheese = spam
    >>> cheese[1] = 'Hello!'
    >>> spam
    [0, 'Hello!', 2, 3, 4, 5]
    >>> cheese
    [0, 'Hello!', 2, 3, 4, 5]

变量包含对列表值的引用,而不是列表值本身。但对于字符串和整数值,变量就包含了字符串或整数值。在变量必须保存可变数据类型的值时,例如列表或字典,Python就使用引用。对于不可变的数据类型的值,例如字符串、整型或元组,Python变量就保存值本身。

5.1.传递引用

当函数被调用时,参数的值被复制给变元。对于列表及字典,这意味着变元得到的是引用的拷贝。当eggs()被调用时,没有使用返回值来为spam赋新值。相反,它直接修改了原来列表。

    def eggs(someParameter):
        someParameter.append('Hello')
    spam = [1, 2, 3]
    eggs(spam)
    print(spam)
    输出:
        [1, 2, 3, 'Hello']

5.2.浅拷贝和深拷贝

在处理列表和字典时,尽管传递引用常常是最方便的方法,但如果函数修改了传入的列表或字典,你可能不希望这些变动影响原来的列表或字典。要做到这一点,Python提供了名为copy的模块,其中包含copy()deepcopy()函数。
第一个函数copy.copy(),可以用来复制列表或字典这样的可变值,而不只是复制引用。spam拷贝后赋值给cheesespamcheese现在是两个变量,修改一个,另外一个的值不变。

    >>> import copy
    >>> spam = ['A', 'B', 'C', 'D']
    >>> cheese = copy.copy(spam)
    >>> cheese[1] = 42
    >>> spam
    ['A', 'B', 'C', 'D']
    >>> cheese
    ['A', 42, 'C', 'D']

如果要复制的列表中包含了列表,那就使用copy.deepcopy()函数来代替,deepcopy()函数将同时复制它们内部的列表。

    import copy
    a = [1, 2, 3, 4, ['a', 'b']] #原始对象
    
    b = a                       #赋值,传对象的引用
    c = copy.copy(a)            #对象拷贝,浅拷贝
    d = copy.deepcopy(a)        #对象拷贝,深拷贝
    
    a.append(5)                 #修改对象a
    a[4].append('c')            #修改对象a中的['a', 'b']数组对象
    
    print( 'a = ', a )
    print( 'b = ', b )
    print( 'c = ', c )
    print( 'd = ', d )

    输出:
        ('a = ', [1, 2, 3, 4, ['a', 'b', 'c'], 5])
        ('b = ', [1, 2, 3, 4, ['a', 'b', 'c'], 5])
        ('c = ', [1, 2, 3, 4, ['a', 'b', 'c']])
        ('d = ', [1, 2, 3, 4, ['a', 'b']])
    >>> spam = [1, ['a', 'b'], 2]
    >>> spam1 = copy.copy(spam)
    >>> spam1
    [1, ['a', 'b'], 2]
    # 经过copy的列表,使用append操作列表里面的列表,两个变量都会变化
    >>> spam[1].append('c')
    >>> spam
    [1, ['a', 'b', 'c'], 2]
    >>> spam1
    [1, ['a', 'b', 'c'], 2]
    >>> spam1[1].append('d')
    >>> spam1
    [1, ['a', 'b', 'c', 'd'], 2]
    >>> spam
    [1, ['a', 'b', 'c', 'd'], 2]
    # 若是直接赋值,则被赋值的会变化,另外一个不会变化,这和python底层数据存储的方式
    # 有关。对于列表,python保存的是指向元素的地址,append会修改地址指向元素的值,而
    # 赋值会直接改变地址,使得被修改的列表指向新的列表,因此赋值不会影响原来的变量的值。
    >>> spam[1] = ['a', 'b']
    >>> spam
    [1, ['a', 'b'], 2]
    >>> spam1
    [1, ['a', 'b', 'c', 'd'], 2]

参考资料

  1. Python编程快速上手-让繁琐的工作自动化
  2. Python基础教程
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值