>>> from env_helper import info; info()
页面更新时间: 2023-12-27 09:26:47
运行环境:
    Linux发行版本: Debian GNU/Linux 12 (bookworm)
    操作系统内核: Linux-6.1.0-16-amd64-x86_64-with-glibc2.36
    Python版本: 3.11.2

3.12. [](){} 一致的容器初始化形式

列表是一个很有用的数据结构,它在Python中属于可变对象,列表中的元素没有限制, 可以重复可以嵌套,操作上支持对单个元素的读取和修改,还支持分片、排序、插人、删除 等。由于其灵活性,在实际应用中经常会看到它的身影。下面的程序遍历列表中的每个元 索,并裉据要求(去掉单词所包含的空格后首宇母是否为大写)生成一个新的list。

>>> words=['Are','abc','pass','busi','fruit','quit']
>>> size=len(words)
>>> newlist=[]
>>> for i in range(size):
>>>     if words[i].strip().istitle():
>>>         newlist.append(words[i])
>>> print(newlist)
['Are']

那么.这段程序有什么问题吗?就程序本身来说并没有什么明显的问题,但有更好的实 现方式。这就是:列表解析(list comprehension)所涉及的内容了。先来了解一T列表解析的基本知识点。 列表解析的语法为:〖expr for iter_item in iterable if cond_expr]。它迭代 iterable 中的每一 个元素,当条件满足的时候便根据表达式expr计算的内容生成一个元素并放入新的列表屮, 依次类推,并最终返冋整个列表。在语法上,它等价于下面代码段:

Newlist =[] for iter_item in iterable:

if cond_expr:

Newlist.append(expr)

其中条件表达式不是必需的.如果没有条件表达式,就直接将expr中计算出的元素加人 List中3列表解析的使用非常灵活。 1)支持多重嵌套。如果需要生成一个二维列表可以使用列表解析嵌套的方式。示例如下:

>>> nested_list=[['Hello ','world'],['goodbye','world']]
>>> nested_list=[[s.upper() for s in xs] for xs in nested_list]
>>> print(nested_list)
[['HELLO ', 'WORLD'], ['GOODBYE', 'WORLD']]

2)支持多重迭代。下面的例子中a, b分别对应两个列表中的元素,丨(a,b) for a in [aVr,l,2]for b in[T,3,4,_b_J ifa !=b]表示:列表[,a,,T,l,2]和[T,3,4,,b,]依次求笛卡儿积之后 并去掉元素值相等的元组之后所剩下的元组的集合。

>>> [(a,b) for a in [' a' , ' 1', 1 , 2] for b in ['l',3,4,'b' ] if a != b]
[(' a', 'l'),
 (' a', 3),
 (' a', 4),
 (' a', 'b'),
 (' 1', 'l'),
 (' 1', 3),
 (' 1', 4),
 (' 1', 'b'),
 (1, 'l'),
 (1, 3),
 (1, 4),
 (1, 'b'),
 (2, 'l'),
 (2, 3),
 (2, 4),
 (2, 'b')]

3)列表解析语法屮的表达式可以是简单表达式,也可以是复杂表达式,甚至是函数d

>>> def f(v):
>>>     if v%2==0:
>>>         v=v**2
>>>     else:
>>>         v=v+1
>>>     return v
>>> [f(v) for v in [2,3,4,-1] if v>0]
[4, 4, 16]
>>> [v**2 if v%2==0 else v+1 for v in [2,3,4,-1] if v>0]
[4, 4, 16]

4)列表解析语法中的以是任意可迭代对象。下面的例子中把文件句柄当做一 个可迭代^•象,可轻易读出文件内容。

>>> fh=open("test.txt","r")
>>> res=[i for i in fh if "abc" in i]
>>> print(res)
['1)使用列表解析吏为直观清晰,代码更为简洁。本节开头的例子改用列表解析,直接 可将代码行数减少为2行,这在大型复杂应用程序中尤为重要,因为这意味着潜在的缺陷较 小,同时代码清晰直观.更容易阅读和理解,可维护性更强。abc']

了解完列表解析的基本知识之后,本节开头的例子你应该知道怎么使用更为简洁了。那 么,为什么要推荐在需要生成列表的时候使用列表解析呢? 1)使用列表解析吏为直观清晰,代码更为简洁。本节开头的例子改用列表解析,直接 可将代码行数减少为2行,这在大型复杂应用程序中尤为重要,因为这意味着潜在的缺陷较 小,同时代码清晰直观.更容易阅读和理解,可维护性更强。 2)列表解析的效率更髙。本节开头的例子用两种不同方法实现后进行测试,测试结果 表明列表解析在时间上有一定的优势.这主要是因为普通循环生成List的时候一般需要多次 调用appendO函数,增加了额外的时间开销。需要说明的是对于大数据处理,列表解析并不 是一个最佳选择,过多的内存消耗可能会导致MemoryError。 除了列表可以使用列表解析的语法之外,其他几种内a的数据结构也支持,比如元组 (tuple)的初始化语法是(expr for iter_item in iterable if cond_expr),而集合(set)的初始化 语法是{expr for iter_item in iterable if cond_expr},甚至字典(diet)也有类似的语法{exprl, expr2 for iterjtem in iterable if cond」;xpr}&它们的使用类似列表解析,但需要注意,因为元 组也适用赋值语句的装筘和拆箱机制,所以需要注意(1 )与(U是不同的:前者为数字1, 后者才代表元组(注意1后面的

>>> type((1))
int
>>> type((1,))
tuple

此外,当函数接受一个可迭代对象参数时,可以使用元组的简写方式。

>>> def foo(a):
>>>     for i in a:
>>>         print(i)
>>> foo([1,2,3])
1
2
3
>>> foo(i for i in range(3) if i%2==0 )
0
2