Python 系列学习之四:列表之高级特性

前言

打算写一系列文章来记录自己学习 Python 3 的点滴;本篇将会重点介绍 python 有关列表的高级特性;

本文为作者的原创作品,转载需注明出处;

列表生成式( List Comprehensions )

A list comprehension is a syntactic construct available in some programming languages for creating a list based on existing lists.

List Comprehensions 是一种语法结构,用来根据一些条件来创建所需要的 list;上述的解释出自 wikipedia,是对列表生成式的一个非常标准的解释;那么python是如何来实现 List Comprehensions 的呢?它是通过range函数来实现的;

首先,我们来通过range来生成一个最简单的列表,

1
2
3
>>> l = range(1, 6)
>>> list(l)
[1, 2, 3, 4, 5]

注意,生成列表的时候,包含左边的边界元素 1,但是不包含右边的边界元素 11;

一层循环

再次,如果我们有这样的一个需求,需要生成这样的一个列表呢?[1x1, 2x2, 3x3, …, 10x10]?该怎么做呢?当然很容易想到,写一个循环来进行分别处理,

1
2
3
4
5
6
>>> L = []
>>> for x in range(1, 6):
... L.append(x * x)
...
>>> L
[1, 4, 9, 16, 25]

上面的方式可以,但是 python 依然觉得繁琐,是否有更简单的方式呢?答案是有的,来看看下面这种 python 的写法,

1
2
>>> [x * x for x in range(1, 6)]
[1, 4, 9, 16, 25]

怎么样,一行代码就实现了上面四行的代码,是的,对了,有没有想到它和什么东西非常的类似?对的,那就是 lambda,为了让匿名函数用一行代码来表示,lambda 默认将执行语句的结果直接当做返回值;这里,其实非常的异曲同工,x * x表达式的结果,既是作为输出的元素;

再次,如果,我们需要对原有的数据做一些清洗的工作呢,比如,我们只取列表中的奇数呢,

1
2
>>> [x * x for x in range(1, 6) if x % 2 == 1]
[1, 9, 25]

两层循环

如果,我们相对两个数组进行全排列呢?那就可以使用两层循环来做,

1
2
>>> [m + n for m in 'ABC' for n in 'XYZ']
['AX', 'AY', 'AZ', 'BX', 'BY', 'BZ', 'CX', 'CY', 'CZ']

循环中使用键值对

1
2
3
>>> d = {'x': 'A', 'y': 'B', 'z': 'C' }
>>> [k + '=' + v for k, v in d.items()]
['y=B', 'x=A', 'z=C']

这个利用了循环遍历 dict 的方式

1
2
3
4
5
6
7
>>> d = {'x': 'A', 'y': 'B', 'z': 'C' }
>>> for k, v in d.items():
... print(k, '=', v)
...
y = B
x = A
z = C

使用场景

比如,我们要列出当前目录中的所有文件和文件夹;

1
2
3
>>> import os 
>>> [d for d in os.listdir('.')] # os.listdir可以列出文件和目录
['.emacs.d', '.ssh', '.Trash', 'Adlm', 'Applications', 'Desktop', 'Documents', 'Downloads', 'Library', 'Movies', 'Music', 'Pictures', 'Public', 'VirtualBox VMs', 'Workspace', 'XCode']

切片

我们以下面这个队列为例,来展示一下如何进行切片操作的,

1
>>> L = ['Michael', 'Sarah', 'Tracy', 'Bob', 'Jack']

正向切片

1
2
>>> L[0:3]
['Michael', 'Sarah', 'Tracy']

如果第一个参数是 0,那么第一个参数可以省略,

1
2
>>> L[:3]
['Michael', 'Sarah', 'Tracy']

从索引 1 开始,取出两个元素,

1
2
>>> L[1:3]
['Sarah', 'Tracy']

反向切片

从倒数第二个元素开始取,取完素有的元素;

1
2
>>> L[-2:]
['Bob', 'Jack']

也可以

1
2
>>> L[-2:-1]
['Bob']

这里要记住的是,倒数第一个元素的坐标是-1

使用切片删除

1
2
3
4
>>> L = ['Michael', 'Sarah', 'Tracy', 'Bob', 'Jack']
>>> L = L[3:]
>>> L
['Bob', 'Jack']

设置切取规则

1
>>> L = list(range(100))

切取前 10 个数,每两个取一个,

1
2
>>> L[:10:2]
[0, 2, 4, 6, 8]

所有数,每 5 个取一个,

1
2
>>> L[::5]
[0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95]

复制

1
>>> L = list(range(100))

使用 [:] 可以直接原样复制一个 list

1
2
>>> L[:]
[0, 1, 2, 3, ..., 99]

tuple

同样可以适用于 tuple,只是切片以后,返回的仍然是一个 tuple,

1
2
>>> (0, 1, 2, 3, 4, 5)[:3]
(0, 1, 2)

字符串

1
2
3
4
>>> 'ABCDEFG'[:3]
'ABC'
>>> 'ABCDEFG'[::2]
'ACEG'