dodo

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

Python核心数据类型——列表

列表是一个任意类型的对象的位置相关的有序集合,它没有固定的大小。大小可变的,通过偏移量进行赋值以及其他各种列表的方法进行调用,能够修改列表。其他更多的功能可以查阅python的标准手册,或者运行help(list)或dir(list)查看list方法的完整清单。

  • 任意对象的有序集合:从功能上看,列表是收集其他对象的地方,同时列表所包含的每一项都保持了从左到右的位置顺序。
  • 通过偏移读取:可以通过列表对象的偏移对其进行索引,从而读取对象的某一部分内容。由于列表的每一项都是有序的,所以可以执行诸如分片、合并之类任务。
  • 可变长度、异构以及任意嵌套:与字符串不同的是,列表可以实地的增长或者缩短(可变长度),并且可以包含任何类型的对象而不仅仅是包含有单个字符的字符串(异构)。列表能够包含其他复杂对象,又能够支持任意嵌套,可以创建列表的子列表的子列表等。
  • 属于可变序列的分类:列表支持在原处修改,列表合并和分片操作是返回新的列表。
  • 对象引用数组:从技术上看,Python列表包含了零个或多个其他对象的引用。

创建

>>> L = list()
>>> L1 = []
>>> type(L),type(L1)
(<class 'list'>, <class 'list'>)

常用列表常量和操作

操作 解释
L = [] 一个空列表
L = [0,1,2,3] 四项:索引为0到3
L = [‘abc’,[‘def’,’ghi’]] 嵌套子列表
L = list(‘spam’),L = list(rang(-4,4)) 可迭代像的列表,连续整数的列表
L[i],L[i][j],L[i:j],len(L) 索引,索引的索引,分片,求长度
L1 + L2 合并
L * 3 重复
for x in L : print(x)   , 3 in L 迭代,成员关系
L.append(4),L.extend([5,6,7]),L.insert(I,x),L.index(1),L.count(x),L.sort(),L.reverse() 方法:增长,排序,搜索,插入,翻转等
del L[k],del L[i:j],L.pop(),L.remove(2),L[i:j] = [] 方法:删除缩短
L[i] = 1,L[i:j] = [4,5,6] 索引赋值,分片赋值
L = [x ** 2 for x in range(5)],list(map(ord,’spam’)) 列表解析
>>> str([1,2])+'34'
'[1, 2]34'
>>> [1,2]+list("34")
[1, 2, '3', '4']

序列操作

可以对列表进行索引、切片等操作,就像字符串所做的操作那样

>>> L = [123,'spam',1.23]
>>> len(L)    #列表长度
3
>>> L[0] #通过索引查找元素
123
>>> L[:-1] #切片返回新列表
[123, 'spam']
>>> L + [4,5,6]  #多个列表合并为新的列表
[123, 'spam', 1.23, 4, 5, 6]
>>> L #原列表未改变
[123, 'spam', 1.23]

原处修改列表

列表是可变的,它们支持原地改变列表对象的操作。当使用列表的时候,可以将它赋值给一个特定项(偏移)或整个片段(分片)来改变它的内容:

>>> L = ['spam','Spam',"SPAM"]
>>> L[1] = 'eggs'
>>> L
['spam', 'eggs', 'SPAM']
>>> L[0:2] = ['eat','more']
>>> L
['eat', 'more', 'SPAM']

索引和分片的赋值都是原地修改,它们对列表进行直接修改,而不是生成一个新的列表作为结果。

类型特定的操作

Python列表与其他语言中的数组有些类似,但要强大得多。其中一个方面就是列表没有固定的约束。如上例子中,列表可以包含不同类型的对象(整数、字符串、浮点数等)。

>>> L = [123,'spam',1.23]
>>> L.append('NI')  #通过append方法在列表末尾增加元素项
>>> L
[123, 'spam', 1.23, 'NI']
>>> L.pop(2) #pop方法移除索引上的元素项
1.23
>>> L
[123, 'spam', 'NI'] 
>>> M = ['bb','aa','cc'] 
>>> M.sort()  #sort方法,默认按升序对列表进行排序
>>> M
['aa', 'bb', 'cc']
>>> M.reverse() #reverse方法进行翻转
>>> M
['cc', 'bb', 'aa']

边界检查

虽然列表没有固定的大小,Python扔不允许引用不存在的元素,超出列表末尾之外的索引总是会报错,对列表末尾范围之外的赋值也报错。

>>> L
[123, 'spam', 'NI']
>>> L[99]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: list index out of range
>>> L[99] = 1
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: list assignment index out of range

嵌套

Python核心数据类型的一个优秀特性是它们支持任意的嵌套。能够以任意的组合对其进行嵌套,并可以多个层次进行嵌套(如:一个列表可以包含一个字典,并在这个字典中包含另外一个列表等)。

>>> M = [[1,2,3],[4,5,6],[7,8,9]]
>>> M
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> M[1]
[4, 5, 6]
>>> M[1][2]
6

列表解析

列表解析表达式(list comperhension expression)提供了一种处理像矩阵这样结构的强大工具。通过简单的索引可以获取行,使用列表解析可以同样简单地获取列。列表解析是通过对序列中的每一项运行一个表达式来创建一个新列表的方法,每次一个,从左到右。列表解析是编写在方括号中(提醒你在创建列表这个事实),并且由使用了同一个变量名的表达式和循环结构组成。

>>> col2 = [row[1] for row in M]
>>> col2
[2, 5, 8]
>>> M
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> [row[1] + 1 for row in M]
[3, 6, 9]
>>> [row[1] for row in M if row[1] % 2  == 0]
[2, 8]
>>> diag = [M[i][i] for i in [0,1,2]]
>>> diag
[1, 5, 9]
>>> doubles = [c * 2 for c in 'spam']
>>> doubles
['ss', 'pp', 'aa', 'mm']
>>> list(map(sum,M))
[6, 15, 24]
>>> [ord(x) for x in 'spam']
[115, 112, 97, 109]

列表函数

函数 描述
len(list) 列表元素个数
max(list) 返回列表元素最大值
min(list) 返回列表元素最小值

列表方法

list.append(obj) 用于在列表末尾添加新的对象。该方法无返回值,但是会修改原来的列表。obj -- 添加到列表末尾的对象。
list.count(obj) 返回元素在列表中出现的次数。obj -- 列表中统计的对象。
list.extend(seq) 用于在列表末尾一次性追加另一个序列中的多个值(用新列表扩展原来的列表)。该方法没有返回值,但会在已存在的列表中添加新的列表内容。seq -- 元素列表。
list.index(obj) 从列表中找出某个值第一个匹配项的索引位置。返回查找对象的索引位置,如果没有找到对象则抛出异常。obj -- 查找的对象。
list.insert(index, obj) 将指定对象插入列表的指定位置。index -- 对象 obj 需要插入的索引位置。obj -- 要插入列表中的对象。
list.pop(index=list[-1]) 移除列表中的一个元素(默认最后一个元素),并且返回该元素的值。index-- 可选参数,要移除列表元素的对象的索引位置。
list.remove(obj) 没有返回值但是会移除列表中的某个值的第一个匹配项。obj -- 列表中要移除的对象。
list.reverse() 没有返回值,但是会对列表的元素进行反向排序。
list.sort([func]) 对原列表进行排序,如果指定参数,则使用比较函数指定的比较函数。没有返回值。func -- 可选参数, 如果指定了该参数会使用该参数的方法进行排序。

Python核心数据类型——字典

除了列表以外,字典(dictionary)是Python之中最灵活的内置数据结构类型。列表是有序的,字典是无序的,他们主要的差别是:字典当中的元素是通过键来存取的,列表是通过偏移量存取。

  • 通过键而不是偏移量来读取
  • 任意对象的无序集合:与列表不同,保存在字典中的项并没有特定的顺序。
  • 可变长、异构、任意嵌套:与列表相似,字典可以在原处增长或缩短(无需生成一份拷贝)。他们可以包含任何类型的对象,而且他们支持任意深度的嵌套(可以包含列表和其他的字典等)。
  • 属于可变映射类型:通过给索引赋值,字典可以在原处修改(可变),但不支持用于字符串和列表中的序列操作。因为字典是无序集合,所以根据固定顺序进行操作是行不通的(例如合并和分片操作)。字典是唯一内置的映射类型(键映射到值得对象)。
  • 对象引用表(散列表):字典是支持键读取的无序对象引用表。从本质上讲,字典是作为散列表(支持快速检索的数据结构)来实现的,一开始很小,并根据要求而增长。Python采用最优化的散列算法来寻找键,因此搜索是很快速的。和列表一样,字典存储的是对象引用(不是拷贝)。

dir(dict)或者help(dict)可以得到完整的dict类型操作清单。当写成常量表达式时,字典以一系列“键:值(key:value)”形式写出来,用逗号隔开,用大括号括起来。

常见字典常量和操作

操作 解释
D = {} 空字典
D = {‘spam’:2,”eggs”:3} 两项目字典
D = {‘food’:{‘ham’:1,’egg’:2}} 嵌套字典
D = dict.fromkeys([‘a’,’b’]) 其他构造技术D = {'b': None, 'a': None}
D = dict(zip(keyslist,valslist)) 关键字、对应的键、值
D = dict(name=’bob’,age=42) D = {'age': 42, 'name': 'bob'}
D['eggs'],D['food']['ham'] 以键进行索引运算
‘eggs’in D 成员判断,键存在测试
D.keys() 方法:键
D.values()
D.items() 键+值
D.copy() 浅copy复制
D.get(key,default) 默认
D.update(D2) 合并
D.pop(key) 删除
len(D) 长度(存储的键的数目)
D[key] = 42 新增/修改键
del D[key] 根据键删除项目
list(D.keys()) 3.0+的D.keys()是生成可迭代视图,要显示需要放在list中
D1.keys() & D2.keys() 与操作,结果为键的set集合
D={x:x*2 for x in range(10)} 字典解析

字典通过键进行索引,被嵌套的字典项是由一系列索引(方括号的键)表示的。当Python创建字典时,会按照任意所选从左到右的顺序来存储项。要取回一个值,需要提供相应的键。

字典的基本操作

>>> D = {'spam':2,'ham':1,'eggs':3}
>>> D['spam']
2
>>> D
{'ham': 1, 'spam': 2, 'eggs': 3}
>>> len(D)
3
>>> 'ham' in D   #与2.0+的has_key()方法相同
True
>>> list(D.keys())
['ham', 'spam', 'eggs']

原处修改字典

可以在原处对字典进行修改、扩展以及缩短而不需要生成新的字典。

>>> D
{'ham': 1, 'spam': 2, 'eggs': 3}
>>> D['ham'] = ['gill','bake','fry']  #修改
>>> D
{'ham': ['gill', 'bake', 'fry'], 'spam': 2, 'eggs': 3}
>>> del D['eggs'] #删除
>>> D
{'ham': ['gill', 'bake', 'fry'], 'spam': 2}
>>> D['brunch'] = 'bacon'#增加
>>> D
{'ham': ['gill', 'bake', 'fry'], 'spam': 2, 'brunch': 'bacon'}

其他字典方法

>>> D = {'spam':2,'ham':1,'eggs':3}
>>> list(D.keys())
['ham', 'spam', 'eggs']
>>> list(D.values())
[1, 2, 3]
>>> list(D.items())
[('ham', 1), ('spam', 2), ('eggs', 3)]
>>> D.get('spam')
2
>>> print(D.get('toast'))#不存在的key返回none值
None
>>> D.get('toast',88)#添加一个默认值时,不存在的可以会显示为默认值
88
>>> D
{'ham': 1, 'spam': 2, 'eggs': 3}
>>> D2 = {'toast':4,'muffin':5}
>>> D.update(D2) #合并字典D2到D字典中
>>> D
{'ham': 1, 'spam': 2, 'toast': 4, 'muffin': 5, 'eggs': 3}
#字典pop方法通过键删除,并返回删除的值
>>> D.pop('muffin')
5
>>> D.pop('toast')
4
>>> D
{'ham': 1, 'spam': 2, 'eggs': 3}
#不同于列表的默认删除最后一个或删除提供的偏移值
>>> L = ['aa','bb','cc','dd']
>>> L.pop()
'dd'
>>> L
['aa', 'bb', 'cc']
>>> L.pop(1)
'bb'
>>> L
['aa', 'cc']

字典用法注意

  • 序列运算无效。字典是映射机制,不是序列。因为字典元素没有顺序的概念,类似串联(有序合并)和分片(提取相邻片段)这样的运算是不能用的。
  • 对新索引赋值会添加项。当编写字典常量是(键是嵌套与常量本身的),或者向现有字典对象的新键赋值时,都会生成键。
  • 键不一定总是字符串。任何不可变对象都可以作为键。

 

字典解析

字典解析隐式地运行一个循环,根据每次迭代收集表达式的键/值结果,使它们来填充一个新的字典。

>>> list(zip(['a','b','c'],[1,2,3])) #zip函数将keys和values成对
[('a', 1), ('b', 2), ('c', 3)]
>>> d = dict(zip(['a','b','c'],[1,2,3])) #zip函数是一个单个调用中从键和值得列表来构建一个字典的方式之一
>>> d
{'b': 2, 'c': 3, 'a': 1}

#字典解析表达式创建字典
>>> d = {k:v for (k,v) in zip(['a','b','c'],[1,2,3])} 
>>> d
{'b': 2, 'c': 3, 'a': 1}
>>> {x:x ** 2 for x in [1,2,3]}
{1: 1, 2: 4, 3: 9}
>>> {x:x ** 2 for x in [1,2,3,4]}
{1: 1, 2: 4, 3: 9, 4: 16}
>>> {c:c * 4 for c in 'spam'}
{'p': 'pppp', 'm': 'mmmm', 'a': 'aaaa', 's': 'ssss'}
>>> {c.lower():c + '!' for c in ['SPAM','EGGS','HAM']}
{'ham': 'HAM!', 'spam': 'SPAM!', 'eggs': 'EGGS!'}

#dict.fromkeys()创建字典与字典解析比较
>>> dict.fromkeys(['a','b','c'],0)
{'b': 0, 'c': 0, 'a': 0}
>>> {k:0 for k in ['a','b','c']}
{'b': 0, 'c': 0, 'a': 0}
>>> dict.fromkeys('spam')
{'p': None, 'm': None, 'a': None, 's': None}
>>> {k:None for k in 'spam'}
{'p': None, 'm': None, 'a': None, 's': None}

字典视图

python3.0+中,字典的keys、values和items都返回视图对象。视图对象是可迭代的,这就意味着对象每次产生一个结果项,而不是在内存中立即产生的结果列表。除了可迭代,字典视图还保持了字典成分的最初顺序,反映字典未来的修改,并且能够支持集合的操作,另一方面,它们不是列表,并且不支持像索引和列表的sort方法这样的操作。

>>> D = dict(a=1,b=2,c=3)
>>> D
{'b': 2, 'c': 3, 'a': 1}
>>> k = D.keys()
>>> k
dict_keys(['b', 'c', 'a'])
>>> list(k)
['b', 'c', 'a']
>>> v = d.values()
>>> v
dict_values([2, 3, 1])
>>> list(v)
[2, 3, 1]
>>> list(d.items())
[('b', 2), ('c', 3), ('a', 1)]
>>> k[0]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'dict_keys' object does not support indexing
>>> list(k)[0]
'b'

可以使用for循环来迫使迭代对象每次迭代上产生一个结果:

>>> for k in D.keys():print(k)
...
b
c
a
>>> for k in D: print(k) #两种写法一样
...
b
c
a

python3.0+ 字典视图并非创建后不能改变——它们可以动态地反映在视图对象创建之后对字典做出的修改:

>>> D
{'b': 2, 'c': 3, 'a': 1}
>>> K = D.keys()
>>> V = D.values()
>>> list(K)
['b', 'c', 'a']
>>> list(V)
[2, 3, 1]
>>> del D['b']
>>> D
{'c': 3, 'a': 1}
>>> list(K)
['c', 'a']
>>> list(V)
[3, 1]

字典视图和集合:

keys方法所返回的Python3.0+的视图对象类似于集合(set),并且支持交集和并集等常见的集合操作;values视图却不一样,因为它们不是唯一的;但items结果却是,如果(key,value)对是唯一的并且可散列的话。由于集合的行为很像是无值的字典,这是一种符合逻辑的对称。就像字典一样,集合的项是无序的、唯一的并且不可变的。

>>> K | {'x':4}
{'x', 'c', 'a'}
>>> V & {'x':4}
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for &: 'dict_values' and 'dict'
>>> V & {'x':4}.values()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for &: 'dict_values' and 'dict_values'
>>> D = dict(a=1,b=2,c=3)
>>> D
{'b': 2, 'c': 3, 'a': 1}
>>> D.keys() & D.keys()
{'b', 'c', 'a'}
>>> D.keys() & 'b'
{'b'}
>>> D.keys() &  {'b':1}
{'b'}
>>> D.keys() | {'b','c','d'}
{'b', 'c', 'd', 'a'}

如果字典项视图是可散列的话,它们是类似于集合的——也就是说,如果它们只包含不可变的对象的话:

>>> D = {'a':1}
>>> list(D.items())
[('a', 1)]
>>> D.items() | D.keys()
{('a', 1), 'a'}
>>> D.items() | D
{('a', 1), 'a'}
>>> D.items() | {('c',3),('d',4)}
{('d', 4), ('a', 1), ('c', 3)}
>>> dict(D.items() | {('c',3),('d',4)})
{'c': 3, 'a': 1, 'd': 4}

排序字典键

由于keys不会返回一个列表,必须要么手动转换为一个列表,要么在一个键视图或字典自身上用sorted调用:

>>> D = {'a':1,'b':2,'c':3}
>>> D
{'b': 2, 'c': 3, 'a': 1}
>>> Ks = D.keys()
>>> Ks.sort()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'dict_keys' object has no attribute 'sort'
>>> Ks = list(Ks)
>>> Ks.sort()
>>> for k in Ks:print(k,D[k])
...
a 1
b 2
c 3
>>> D
{'b': 2, 'c': 3, 'a': 1}
#通过键视图
>>> Ks = D.keys()
>>> for k in sorted(Ks):print(k,D[k])
...
a 1
b 2
c 3
>>> D
{'b': 2, 'c': 3, 'a': 1}
#通过字典自身
>>> for k in sorted(D): print(k,D[k]) #或者直接sorted(D)
...
a 1
b 2
c 3

字典内的函数

函数 描述
len(dict) 返回字典元素个数,即键的总数。dict -- 要计算元素个数的字典。
str(dict) 返回字符串,将值转化为适于人阅读的形式,以可打印的字符串表示。dict -- 字典。
type(dict) 返回输入的变量类型,如果变量是字典就返回字典类型。dict -- 字典。
dict.clear() 没有任何返回值。删除字典内所有元素。
dict.copy() 返回一个字典的浅复制。
dict.fromkeys(seq[, value])) 创建一个新字典,以序列seq中元素做字典的键,value为字典所有键对应的初始值。seq -- 字典键值列表。value -- 可选参数, 设置键序列(seq)的值,默认为None。
dict.get(key, default=None) 返回指定键的值,如果值不在字典中返回默认值None。key -- 字典中要查找的键。default -- 如果指定键的值不存在时,返回该默认值值。
dict.items() 返回可遍历的(键, 值) 元组数组。
dict.keys() 返回一个字典所有的键。可迭代
dict.setdefault(key, default=None) get()方法类似, 如果键不已经存在于字典中,将会添加键并将值设为默认值。key -- 查找的键值。default -- 键不存在时,设置的默认键值。
dict.update(dict2) 把字典dict2的键/值对更新到dict里,dict2 -- 添加到指定字典dict里的字典。
dict.values() 返回字典中的所有值。可迭代
posted on 2016-11-22 21:49  dodo‘s  阅读(4568)  评论(0编辑  收藏  举报