“列表”是一个值,它包含多个字构成的序列。属于“列表值”指的是列表本身(它作为一个值,可以保存在变量中,或传递给函数,像所有其他值一样),而不是指列表值之内的那些值。
列表用左方括号开始,右方括号结束,即[]。列表中的值也成为“表项”。表项用逗号分隔。
['cat', 'bat', 'rat', 'elephant']
>>> spam = ['cat', 'bat', 'rat', 'elephant'] >>> 'Hellp' + spam[0] 'Hello cat'
请注意,表达式'Hellp' + spam[0]求值为'Hello' + 'cat',因为spam[0]求值为字符串'cat'。这个表达式也因此求值为'Hello cat'
下标只能是整数,不能是浮点值。列表也可包含其他列表值。这些列表的列表中的值,可以通过多重下标来访问。
>>> spam = [['cat', 'bat'], [10, 20, 30, 40, 50]] >>> spam[ 0] ['cat', 'bat'] >>> spam[ 0][ 1] 'bat' >>> spam[ 1][ 4] 50
第一个下标表明使用哪个列表值,第二个下标表明该列表值中的值。
虽然下标从0开始并向上增长,但也可以用负整数作为鞋标。整数值-1指的是列表中的最后一个下标,-2指的是列表中倒数第二个下标。
就像下标可以从列表中取得单个值一样,”切片“可以从列表中取得多个值,结果是一个新列表。切片输入在一对方括号中,像下标一样,但它有两个冒号分隔的整数。
请注意下标和切片的不同。
spam[2]是一个列表和下标(一个整数)
spam[1:4]是一个列表和切片(两个整数)
在一个切片中,第一个整数是切片开始处的下标。第二个整数是切片结束处的下标。切片向上增长,直至第二个下标的值,但不包括它。切片求值为一个新的列表值。
>>> spam = ['cat', 'bat', 'rat', 'elephant'] >>> spam[ 0: 4] ['cat', 'bat', 'rat', 'elephant'] >>> spam[ 1: 3] ['bat', 'rat'] >>> spam[ 0:- 1] ['cat', 'bat', 'rat']
作为快捷方法,你可以省略切片中冒号两边的一个下标或两个下标。省略第一个下标相当于使用0,或列表的开始。省略第二个下标相当于使用列表的长度,意味着切片直至列表的末尾。
len()函数将返回传递给它的列表中值的个数,就像它能计算字符串中字符的个数一样。
>>> spam = ['cat', 'dog', 'moose'] >>> len(spam) 3
一般情况下,赋值语句左边是一个变量名,就像spam = 4。但是,也可使用列表的下标来改变下标处的值。
>>> 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]
+操作符可以连接两个列表,得到一个新列表,就像它将两个字符串合并成一个新字符串一样。*操作符可以用于一个列表和一个整数,实现列表的复制。
>>> [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']
del语句将删除列表中下标处的值,表中被删除值后面的所有值,都将向前移动一个下标。
>>> spam = ['cat', 'bat', 'rat', 'elephant'] >>> del spam[ 2] >>> spam ['cat', 'bat', 'elephant'] >>> del spam[ 2] >>> spam ['cat', 'bat']
del语句也可用于一个简单变量,删除它,作用就像是”取消赋值“语句。如果在删除之后试图使用该变量,就会遇到NameError错误,因为该变量已不再存在。
方法pop()删除列表末尾的元素,并让你能够接着使用它。
>>> spam = ['cat', 'bat', 'rat', 'elephant'] >>> spam ['cat', 'bat', 'rat', 'elephant'] >>> spam_poped = spam.pop() >>> spam_poped 'elephant'
实际上,可以使用pop()来删除列表中任意位置的元素,只需在圆括号中指定要删除元素的索引即可:
>>> spam = ['cat', 'bat', 'rat', 'elephant'] >>> spam_poped = spam.pop(1) >>> spam_poped 'bat'
使用列表的好处在于,现在数据放在一个结构中,所以程序能够更灵活的处理数据,比放在一些重复的变量中方便。
从技术上说,循环是针对一个列表或类似列表中的每个值,重复地执行代码块。一个常见的python技巧,是在for循环中使用range(len(someList)),迭代列表的每一个下标。
利用in和not in操作符,可以确定一个值是否在列表中。像其他操作一样,in和not 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
多重赋值技巧是一种快捷方式,让你在一行代码中,用列表中的值为多个变量赋值。所以不必像这样:
>>> cat = ['fat', 'black', 'loud'] >>> size = cat[ 0] >>> color = cat[ 1] >>> disposition = cat[ 2]
而是输入下面的代码:
>>> cat = ['fat', 'black', 'loud'] >>> size, color, disposition = cat
但是变量的数目和列表的长度必须严格相等,否则Python将会给出ValueError。
在对变量赋值时,常常会用到变量本身。例如,将42赋给变量spam之后,用下面的代码让spam的值增加1:
>>> spam = 42 >>> spam = spam + 1 >>> spam 43
作为一种跨界方式,可以用增强的赋值操纵符+=来完成同样的事:
>>> spam = 42 >>> spam += 1 >>> spam 43
方法和函数是一回事,只是它是调用在一个值上。每种数据类型都有它自己的一组方法。
列表值有一个index()方法,可以传入一个值,如果该值存在于列表中,就返回它的下标。如果该值不在列表中,python就报ValueError。
如果列表中存在重复的值,就返回它第一次出现的下标。
要在列表中添加新值,就使用append()和insert()方法。
>>> spam = ['cat', 'dog', 'bat'] >>> spam.append(' moose') >>> spam ['cat', 'dog', 'bat', 'moose']
前面的append()方法调用,将参数添加到列表末尾。insert()方法可以在列表任意下标处插入一个值。insert()方法的第一个参数是新值的下标,第二个参数是要插入的新值。
>>> spam = ['cat', 'dog', 'bat'] >>> spam.insert( 1, 'chicken') >>> spam ['cat', 'chicken', 'dog', 'bat']
方法属于单个数据类型。append()和insert()方法是列表方法,只能在列表上调用,不能再其他值上调用。
给remove()方法传入一个值,它将从被调用的列表中删除。
>>> spam = ['cat', 'bat', 'rat', 'elephant'] >>> spam.remove('bat') >>> spam ['cat', 'rat', 'elephant']
试图删除列表中不存在的值,将导致ValueError错误。如果该值在列表中出现多次,只有第一次出现的值会被删除。
如果知道想要删除的值在列表中的下标,del语句就会很好用。
数值的列表或字符串的列表,能用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()方法,你应该注意3件事。首先,sort()方法放长对列表排序。不要写spam = spam.sort()这样的代码,试图记录返回值。
其次,不能对既有数字由于字符串值得列表进行排序,因为python不知道如何比较它们。
第三,sort()方法对字符串排序时,使用"ASCII字符顺序",而不是实际的字典顺序。这意味着大写字母排在小写字母之前。因此在排序时,小写的a在大写Z之后。
如果需要按照普通字典顺序来拍寻,就在sort方法调用时,将关键字参数key设置为str.lower。
>>> spam = ['a', 'z', 'A', 'Z'] >>> spam.sort(key=str.lower) >>> spam ['a', 'A', 'z', 'Z']
这将导致sort()方法将列表中所有的表项当成小写,但实际上并不会改变它们在列表中的值。
要保留列表元素原来的排列顺序,同时以特定的顺序呈现它们,可使用函数sorted()。函数sorted()让你能够按特定顺序显示列表元素,同时不影响它们在列表中的原始排列顺序。
>>> spam = ['a', 'z', 'A', 'Z'] >>> sorted(spam) ['A', 'Z', 'a', 'z'] >>> spam ['a', 'z', 'A', 'Z']
要反转列表元素的排列顺序,可使用方法reverse()。
>>> spam = ['a', 'z', 'A', 'Z'] >>> spam.reverse() >>> spam ['Z', 'A', 'z', 'a']
类似列表的类型:字符串和元组
列表并不是唯一表示序列值的数据类型。
但是列表和字符串在一个重要的方面是不同的。列表是”可变的“数据类型,它的值可以添加、删除或改变。而字符串是”不可变的“,它不能被更改。尝试对字符串中的一个字符重新赋值,将导致TypeError错误。
”改变“一个字符的正确方式,是使用切片和连接。构造一个”新的“字符串,从老的字符串那里赋值一些部分。
>>> name = 'Zophie a cat' >>> newName = name[ 0: 7] + 'the' + name[ 8: 12] >>> name 'Zophie a cat' >>> newName 'Zophie the cat'
下面代码中的第二行并没有修改eggs:
>>> eggs = [1, 2, 3] >>> eggs = [4, 5, 6] >>> eggs [4, 5, 6]
这里eggs中的列表值并没有改变,而是整个新的不同的列表值([4, 5, 6])覆写了老的列表值。
除了两个方面,”元组“数据类型几乎与列表数据类型一样。首先,元组输入时用圆括号(),而不是方括号[]。
>>> eggs = ('hello', 42, 0. 5) >>> eggs[ 0] 'hello' >>> eggs[ 1: 3] (42, 0. 5) >>> len( eggs) 3
但元组与列表的主要区别在于,元组像字符串一样是不可改变的。元组不能让它们的值被修改、添加或删除。如果改变会出现TypeError出错信息。
如果元组只有一个值,你可以在括号内该值的后面跟上一个逗号,表明这种情况。否则,python将认为你只是在一个普通括号内输入了一个值。逗号告诉python,这是一个元组。
>>> type((' hello',)) < class 'tuple'> >>> type((' hello')) < class 'str'>
用list()和tuple()函数来转换类型
正如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']
引用
变量保存字符串和整数值。
>>> spam = 42 >>> cheese = spam >>> spam = 100 >>> spam 100 >>> cheese 42
你将42赋给spam变量,然后考本spam中的值,将它赋给变量cheese。当将spam中的值改变为100时,这不会影响cheese中的值,这是因为spam和cheese是不同的变量,保存了不同的值。
当你将列表赋给一个变量时,实际上是将列表的“引用”赋给了该变量。引用是一个值,指向某些数据。列表引用是指向一个列表的值。
>>> 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]
当创建按列表时,你将对它的引用赋给了变量。
但下一行只是将spam中的列表引用拷贝到cheese,而不是列表值本身。这意味着存储在spam和cheese中的值,现在指向了同一个列表。底下只有一个列表,因为列表本身实际从未赋值。
所以当你修改cheese变量的第一个元素时,也修改了spam指向的同一个列表。
变量包含对列表值得引用,而不是列表值本身。但对于字符串和整数值,变量就包好了字符串或整数值。
当函数被调用时,参数的值被复制给变元。对于列表这意味着变元得到的是引用的拷贝。
def eggs(someParameter): someParameter.append('Hello') spam = [1, 2, 3] eggs(spam) print(spam)
请注意,当eggs()被调用时,没有使用返回值来为spam赋新值。相反,它直接当场修改了该列表。
[1, 2, 3, 'Hello']
Python提供了名为copy的模块,其中包含copy()和deepcopy()函数。
第一个函数copy.copy(),可以用来复制列表或字典的可变值,而不只是复制引用。
>>> import copy >>> spam = ['A', 'B', 'C', 'D'] >>> cheese = copy. copy( spam) >>> cheese[ 1] = 42 >>> spam ['A', 'B', 'C', 'D'] >>> cheese ['A', 42, 'C', 'D']
现在spam和cheese变量指向独立的列表,这就是为什么当你将42赋给下标1时,只有cheese中的列表被改变。
如果要复制的列表中包含了列表,那就使用copy.deepcopy()函数来代替。deepcopy()函数将同时复制它们内部的列表。