旷世的忧伤

Huoty's Blog

Python 序列:列表、元组

像字符串类型一样,列表类型也是序列式的数据类型,可以通过下标或者切片操作来访问某一个或者某一块连续的元素。然而,相同的方面也就这些,字符串只能由字符组成,而且是不可变的(不能单独改变它的某个值),而列表则是能保留任意数目的 Python 对象的灵活的容器。

列表不仅可以包含 Python 的标准类型,而且可以用用户定义的对象作为自己的元素。列表可以包含不同类型的对象。列表可以执行 pop,empt,sort,reverse 等操作.列表也可以添加或者减少元素。还可以跟其他的列表结合或者把一个列表分成几个。可以对单独一个元素或者多个元素执行 insert,update,或者 remove 操作。

用列表还可以轻松的构建其他数据结构,例如:堆栈,队列等。

列表的创建与值的访问

列表由方括号([])来定义,元素间用逗号(,)隔开,同事页可以用工厂方法 list 来创建。如下所示:

>>> alist = [123, "abc", 123.456, [1, "a", 2.3], 7-8j]
>>> another_list = [None, "something to see here"]
>>> print alist
[123, 'abc', 123.456, [1, 'a', 2.3], (7-8j)]
>>> print another_list
[None, 'something to see here']
>>> empty_list = []
>>> print empty_list
[]
>>> list("I am huoty")
['I', ' ', 'a', 'm', ' ', 'h', 'u', 'o', 't', 'y']

访问列表中值用切片操作符([]),这和字符串一样。要更新列表可以通过在等号的左边指定一个索引或者索引范围的方式来更新一个或几个元素,或者可以用 append() 方法来追加元素到列表中去。要删除列表中的元素,如果你确切的知道要删除元素的素引可以用 del 语句,否则可以用remove()方法。如下所示:

>>> alist = [123, "abc", 123.456, [1, "a", 2.3], 7-8j]
>>> alist[2]
123.456
>>> alist
[123, 'abc', 123.456, [1, 'a', 2.3], (7-8j)]
>>> blist = [1.2, 2.3, 3.4]
>>> alist.append(blist)
>>> alist
[123, 'abc', 123.456, [1, 'a', 2.3], (7-8j), [1.2, 2.3, 3.4]]
>>> alist[0] = "hahaha"
>>> alist
['hahaha', 'abc', 123.456, [1, 'a', 2.3], (7-8j), [1.2, 2.3, 3.4]]
>>> del alist[1]
>>> alist
['hahaha', 123.456, [1, 'a', 2.3], (7-8j), [1.2, 2.3, 3.4]]
>>> alist.remove("hahaha")
>>> alist
[123.456, [1, 'a', 2.3], (7-8j), [1.2, 2.3, 3.4]]

列表解析

Python 中没有专门用于列表类型的操作符,但列表有一个非常重要的操作,即列表解析。列表解析( List comprehensions, 或缩略为 list comps ) 来自函数式编程语言 Haskell . 它是一个非常有用, 简单, 而且灵活的工具, 可以用来动态地创建列表。列表解析的语法:

[expr for iter_var in iterable]

列表解析通过 for 循环迭代 iterable 对象的所有条目,并将 expr 应用于序列的每个成员, 最后的结果值是该表达式产生的列表。 迭代变量并不需要是表达式的一部分。

列表类型的内建函数

list.append(obj)  向列表中添加一个对象 obj
list.count(obj)  返回一个对象 obj 在列表中出现的次数
list.extend(seq)  把序列 seq 的内容添加到列表中
list.index(obj, i=0, j=len(list))  返回 list[k] == obj 的 k 值,并且 k 的范围在 i<=k<j;否则引发 ValueError 异常.
list.insert(index, obj)  在索引量为 index 的位置插入对象 obj.
list.pop(index=-1)  删除并返回指定位置的对象,默认是最后一个对象
list.remove(obj)  从列表中删除对象 obj
list.reverse()  原地翻转列表
list.sort(func=None,key=None, reverse=False)  以指定的方式排序列表中的成员,默认的排序算法是归并排序,如果 func 和 key 参数指定, 则按照指定的方式比较各个元素,如果 reverse 标志被置为 True, 则列表以反序排列.

关于可变对象的方法

那些可以改变对象值的可变对象的方法是没有返回值的!

不要陷入一个误区:调用一个方法就返回一个值。一些操作可变对象的方法是不需要有返回值,它们只需在原对象的基础上修改即可。

在使用可变对象的方法如 sort(),extend()和 reverse()的时候要注意,这些操作会在列表中原地执行操作,也就是说现有的列表内容会被改变,但是没有返回值! 是的,与之相反,字符串方法则有返回值。因为字符串是不可变的,不可变对象的方法是不能改变它们的值的,所以它们必须 返回一个新的对象。

如果确实需要返回一个新的列表对象,那么建议看一下 Python2.4 以后加入的 reversed()和 sorted()内建函数。它们像列表的方法一样工作,不同的是它们可以用做表达式,因为它们返回一个对象。同时原来的那个列表还是那个列表,没有改变,而你得到的是一个新的对象。

元组操作

元组是跟列表非常相近的另一种容器类型。元组和列表看起来不同的一点是元组用的是圆括号()而列表用的是方括号。而功能上,元组和列表相比有一个很重要的区别,元组是一种不可变类型。正因为这个原因,元组能做一些列表不能做的事情,例如,用做一个字典的 key。另外当处理一组对象时,这个组默认是元组类型。

元组类型在很多操作上都跟列表一样,许多用在列表上的方法在元组上也能用,它们的主要不同在于元组是不可变的,或者说是只读的,所以那些用于更新列表的操作,比如用切片操作来更新一部分元素的操作,就不能用于元组类型。因为元组是容器对象,所以不能试图改变容器中的一个或者多个元素,切片操作符也不能用作左值进行赋值。

在创建一个单元素元组时,由于圆括号包裹的一个单一元素首先被作为分组操作,而不是作为元组的分界符,所以可能得不到你想要的结果。例如 (‘xyz’) 实际上只是一个字符串 ‘xyz’。因此,要创建单一元素元组时,需要在第一个元素后面添一个逗号(,)来表明这是一个元组而不是在做分组操作。例如 (‘xyz’,) 则表示一个单元素元组。

字典的键值必须是可哈希的对象,元组变量符合这个标准,所以可以用作字典的键值。用于元组的不可变性,可以将元组作为参数传递给其他函数,这样函数就不会改变传递所传递的值。

为什么要区分列表和元组

为什么我们要区分元组和列表变量?这个问题也可以被表述为“我们真的需要两个相似的序列类型吗?”。

一个原因是在有些情况下,使用其中的一种类型要优于使用另一种类型。最好使用不可变类型变量的一个情况是,如果你在维护一些敏感的数据,并且需要把这些数据传递给一个并不了解的函数(或许是一个根本不是你写的 API),作为一个只负责一个软件某一部分的工程师,如果你确信你的数据不会被调用的函数篡改,你会觉得安全了许多。

一个需要可变类型参数的例子是,如果你在管理动态数据集合时。你需要先把它们创建出来,逐渐地或者不定期的添加它们,或者有时还要移除一些单个的元素。这是一个必须使用可变类型对象的典型例子。幸运的是,通过内建的 list()和 tuple()转换函数,你可以非常轻松的在两者之间进行转换。

list()和 tuple()函数允许你用一个列表来创建一个元组,反之亦然.如果你有一个元组变量,但你需要一个列表变量因为你要更新一下它的对象,这时 list()函数就是你最好的帮手。如果你有一个列表变量,并且想把它传递给一个函数,或许一个 API,而你又不想让任何人弄乱你的数据,这时 tuple()函数就非常有用。

Top