python的内置对象类型(3)——列表类型和字典类型

本文详细介绍了Python的列表和字典两种内置对象类型。列表是可变的有序对象集合,支持序列操作、类型特定操作如append、pop等,支持任意嵌套和列表解析。字典是通过键进行索引的映射,支持原处修改,包括fromkeys、values、items等方法。文章还探讨了字典的排序、3.0版本的变化以及如何处理键不存在的情况。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

列表

python的列表对象是最通用的序列,是一个任意类型的对象的位置相关的有序集合。它大小可变的,通过偏移量进行赋值以及其他各种列表方法进行调用,可以修改列表的大小。主要特点有:任意对象的有序集合;通过偏移读取,可变长、异构以及任意嵌套,可变序列,对象引用数组(实际上,在python解释器内部,列表就是c数组而不是链接结构)

1)序列操作

列表是序列的一种,所以支持字符串用过的序列操作。唯一的区别是其结果往往是列表。+合并,*重复,for x in L:print(x)迭代,

>>> L = list([123,'spam',1.23])
>>> len(L)
3
>>> L[:-1]
[123, 'spam']
>>> L + [1,2,3]
[123, 'spam', 1.23, 1, 2, 3]

>>> L1 = list(range(-4,4))
>>> L1
[-4, -3, -2, -1, 0, 1, 2, 3]

边界检查:尽管列表没有固定大小,python仍不允许引用不存在的元素,超出列表末尾之外的索引总是会导致错误的,对列表超出范围之外的赋值亦是如此。

2)类型特定的操作

列表比其他语言的数组强大的多,其中一个方面就是列表没有固定类型的约束。此外,没有固定大小,可以根据需要增加或减少列表大小,来响应特定的操作。

append在尾部加入一项,pop移除给定偏移量的一项(默认移除最后一项),insert任意插入,remove按值移除元素,extend加入列表的全部元素。列表sort方法默认升序进行排序,而reverse对列表进行翻转。

内置函数sort可以排序任意集合(不只是列表),并且针对结果返回一个新的列表(而不是原处修改)

>>> L.append('qq')
>>> L
[123, 'spam', 1.23, 'qq']
>>> L.pop(2)
1.23
>>> L.insert(1,'wechat')
>>> L
[123, 'wechat', 'spam', 'qq']
>>> L.remove('qq')
>>> L
[123, 'wechat', 'spam']

>>> L.extend([4,4,7])
>>> L
[123, 'wechat', 'spam', 4, 4, 7]
>>> L.pop()
7
>>> L.count(4)
2

>>> M = [2,5,9,3,6]
>>> M.sort()
>>> M
[2, 3, 5, 6, 9]
>>> M.reverse()
>>> M
[9, 6, 5, 3, 2]

>>> L = ['abc', 'ABD', 'aBe']
>>> L.sort()
>>> L
['ABD', 'aBe', 'abc']
>>> L.sort(key = str.lower)
>>> L
['abc', 'ABD', 'aBe']
>>> L.sort(key = str.lower,reverse = True)
>>> L
['aBe', 'ABD', 'abc']

>>> L = ['abc','ABC','aBe']
>>> L
['abc', 'ABC', 'aBe']
>>> sorted(L,key = str.lower,reverse = True)     # 在排序之前,用列表解析将其转换为小写
['aBe', 'abc', 'ABC']
>>> L = ['abc','ABC','aBe']
>>> sorted([x.lower() for x in L], reverse = True)
['abe', 'abc', 'abc']

不同类型之间的排序在3.0中发生异常 

其他常见的列表操作

>>> L = ['eat','run','jump','sleep']
>>>
>>> del L[0]
>>> L
['run', 'jump', 'sleep']
>>> L
['run', 'jump', 'sleep']
>>> del L[1:]
>>> L
['run']

3)嵌套

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[0][2]
3

4)列表解析和迭代

是处理像矩阵这样结构强大工具,使用列表解析可以简单地获取列。它是一种通过对序列中地每一项运行一个表达式来创建一个新列表的方法。

解析语法可以创建产生所需要结果的生成器,如内置的sum函数。内置map函数也可以做类似的事情,它将所有的值包装在列表中返回。

>>> col1 = [row[1] for row in M]    # 把矩阵M的每一row中的row[1],放在一个新的列表中
>>> col1
[2, 5, 8]

>>> M = [[1,2,3],[4,5,6],[7,8,9]]
>>> G = (sum(row) for row in M)
>>> next(G)
6
>>> next(G)
15
>>> list(map(sum,M))        
[6, 15, 24]


>>> for x in [1,2,3]:        # 迭代
...  print(x,end = '')
...
123>>>

解析语法可以用来创建列表,字典和集合。

字典

字典是一种映射(mapping),是其他对象的集合,通过键而不是相对位置存储的。映射并没有任何可靠的从左向右的顺序,它具有可变性,就像列表那样。

1)映射操作

通过键对字典进行索引来读取或改变键所关联的值。字典的索引操作使用的是和序列相同的语法,方括号中的是键,而不是相对位置。

与列表禁止边界外的赋值不同,对一个新的字典键会创建该键。

>>> D = {'food':'Spam','quantity':4}
>>> D['quantity'] += 1
>>> D
{'food': 'Spam', 'quantity': 5}
>>> D = {}
>>> D['name'] = 'Bob'
>>> D['job'] = 'dev'
>>> D['age'] = 40
>>> D
{'name': 'Bob', 'job': 'dev', 'age': 40}

2) 重访嵌套(支持原处修改字典)

一般来说,字典可以取代搜索数据结构,并且可以表示多种结构信息的类型。当读取嵌套对象的元素时,只要简单地把索引操作串联起来就可以了。

>>> rec = {'name':{'first':'Bob','last':'Smith'},'job':['deb','mgr'],'age':40.5}
>>> rec['name']['first']
'Bob'
>>> rec['job'][-1]
'mgr'
>>> rec['job'].append('janitor')
>>> rec
{'name': {'first': 'Bob', 'last': 'Smith'}, 'job': ['deb', 'mgr', 'janitor'], 'age': 40.5}
# 一个嵌套的字典作为name值,支持了多个部分,并用一个嵌套的列表作为job的值从而支持多个角色和未来扩展

注意: 最后一个操作时如何扩展嵌入job列表的,因为job列表时字典所包含的一部分独立的内存,它可以自由地增加或减少。

3)字典方法

创建字典的方法有4种:fromkeys方法利用键初始化字典

>>> D1 = {'name':'mel', 'age':45}                # 事先拼出字典
>>> D2 = {}
>>> D2['name'] = 'mel'                           # 动态建立
>>> D2['age'] = 45
>>> D3 = dict(name = 'mel', age = 45)            # 关键字参数形式,键必须是字符串才行
>>> D4 = dict([('name','mel'),('age',45)])        # 键值对形式,运行时将键和值建成序列
>>> D1
{'name': 'mel', 'age': 45}
>>> D2
{'name': 'mel', 'age': 45}
>>> D3
{'name': 'mel', 'age': 45}
>>> D4
{'name': 'mel', 'age': 45}

# 简单地传入一个建列表,以及所有键的初始值

>>> D5 = dict.fromkeys(['a','b'],0)
>>> D5
{'a': 0, 'b': 0}

values和items方法分别返回字典的值列表和(key,value)对元组;get方法能够在键不存在时,返回默认值(None,或者用户自定义的默认值)。update把一个字典的键和值合并到另一个字典中,盲目地覆盖相同键的值。

>>> D = {'spam':2,'ham':1,'eggs':3}
>>> D.values()
dict_values([2, 1, 3])
>>> list(D.values())
[2, 1, 3]
>>> list(D.items())
[('spam', 2), ('ham', 1), ('eggs', 3)]
>>> D.get('spam')
2
>>> D.get('toast')
>>> print(D.get('toast'))
None
>>> D.get('toast',88)
88
>>> D
{'spam': 2, 'ham': 1, 'eggs': 3}
>>> D1 = {'toast':4, 'muffin':5}
>>> D.update(D1)
>>> D
{'spam': 2, 'ham': 1, 'eggs': 3, 'toast': 4, 'muffin': 5}
>>> D2 = {'ham':6}
>>> D.update(D2)
>>> D
{'spam': 2, 'ham': 6, 'eggs': 3, 'toast': 4, 'muffin': 5}
>>> D.pop('eggs')
3
>>> D
{'spam': 2, 'ham': 6, 'toast': 4, 'muffin': 5}

4)键的排序:for循环

>>> D = {'c':3,'a' :1,'b':2}
>>> D
{'c': 3, 'a': 1, 'b': 2}
>>> ks = list(D.keys())
>>> ks
['c', 'a', 'b']
>>> ks.sort()
>>> for key in ks:
...     print(key,'=>',D[key])
...
a => 1
b => 2
c => 3

>>> D
{'c': 3, 'a': 1, 'b': 2}
>>> for key in sorted(D):                # sorted能直接作用于字典上,不必用keys方法来得到一个序列
                                        #,因为字典是一个可迭代的对象。
...     print(key,'=>',D[key])
...
a => 1
b => 2
c => 3

迭代和优化:for循环和列表解析表达式都是通用的迭代工具。迭代协议表示在内存中物理存储的序列,或一个在迭代操作情况下每次产生一个元素的对象。如果一个对象在响应next之前先用一个对象对iter内置函数做出响应,那么它属于后一种情况。从左向右扫描一个对象的每个python工具都使用迭代协议。

和列表解析相关的函数编程工具,如map和filter,通常运行得比for循环快:这是对有大数据集合的程序有重大影响的特性之一。

获取一个不存在的东西往往是一个程序错误。但是,在一些通用程序中,我们编写程序时并不是总知道当前存在什么键。在这种情况下,我们如何处理和避免错误发生呢?

一个技巧是首先测试,in表达式允许我们查询字典中一个键是否存在,并可以通过使用python的if语句对结果进行分支处理。

>>> D = {'a':1,'c':7,'b':2}
>>> D
{'a': 1, 'c': 7, 'b': 2}
>>> 'f' in D
False

 另外还有get方法,try语句,if/else表达式。

注意:1)序列运算无效(类似合并和分片都不能用);2)键不一定是字符串

字典用于稀疏数据结构

>>> Matrix = {}
>>> Matrix[(2,3,4)] = 88
>>> Matrix[(7,8,9)] = 99
>>> X = 2; Y = 3; Z = 4
>>> Matrix[(X,Y,Z)]
88
>>> Matrix
{(2, 3, 4): 88, (7, 8, 9): 99}

如何避免miss-key错误?

>>> if(2,3,6) in Matrix:
...     print(Matrix[(2,3,6)])
... else:
...     print(0)
...
0
>>> try :
...     print(Matrix[(2,3,6)])
... except KeyError:
...     print(0)
...
0
>>> Matrix.get((2,3,4),0)
88
>>> Matrix.get((2,3,6),0)
0

5)在3.0中的变化

(1)支持一种新的字典解析表达式,这是列表和集合解析的“近亲”

zip函数是在一个单个调用中从键和值的列表来构建一个字典的方式之一。

>>> list(zip(['a','b','c'],[1,2,3]))
[('a', 1), ('b', 2), ('c', 3)]
>>> D = dict(zip(['a','b','c'],[1,2,3]))
>>> D
{'a': 1, 'b': 2, 'c': 3}
>>> D1 = {c.lower(): c + '!' for c in ['SPAM','EGGS','HAM']}
>>> D1
{'spam': 'SPAM!', 'eggs': 'EGGS!', 'ham': 'HAM!'}

(2)对于D.key、D.values和D.items方法,返回可迭代的视图,而不是列表。它支持交集和并集等常见的集合操作,但values视图不是这样的,因为他不是唯一的。

(3)需要新的编码方式通过排序键来遍历:转换为一个列表,要么在一个键视图或者字典身上使用sorted函数

>>> D = {'a':1, 'b':2, 'c':3}
>>> D
{'a': 1, 'b': 2, 'c': 3}
>>> K = D.keys()
>>> kl  = list(K)
>>> kl.sort()
>>> for k in kl:print(k,D[k])
...
a 1
b 2
c 3

>>> for k in sorted(K):print(k,D[k])
...
a 1
b 2
c 3

(4)不再直接支持相对大小的比较——取代的是手动比较

(5)不再有D.has_key方法,使用in成员关系测试

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

vinkuan

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值