变得更pythonic(懒)-三元表达式和列表解析式

也许你只是刚刚开始接触python, 也许你已经走上python的不归路,也许你厌倦了条件循环的换行和缩进。To be pythonic, 你不会错过每一个由繁到简的转变。本文简单介绍了python的三元表达式,列表解析式以及它们的结合用法,轻轻松松使用一行代码解决判断与循环,走上pythonic(懒)之路。

##三元表达式
在学习python之前你可能已经接触过了三目运算符

判断条件 ? 为真的结果 : 为假的结果

python并没有三目运算符这样的语法,取而代之的是我们的三元表达式

(True) if condition else (False)

举个栗子让我们来看看什么是三元表达式

1
2
3
4
5
6
>>> a = 5;b = 3
>>> if a > b:
... c = True
...
>>> c
True

使用三元表达式

1
2
3
4
>>> a = 5;b = 3
>>> c = True if a > b else False
>>> c
True

或者

1
2
3
>>> condition =True
>>> print( 1 if condition else 0)
1

同三目运算符一样, 三元表达式不支持复杂的操作。如果三元表达式支持复杂的操作,那么将所有代码挤到一行里并不是一个明智的选择。那些简单的if statement 才是三元表达式的用武之地。

##列表解析式

###什么是列表解析式?

列表解析式就是将任何可迭代的对象转换成列表的工具。你可以在转换过程中添加条件进行过滤,

###for循环与列表解析式

任何列表解析式都可以改写成for循环,因为其本事就是由for循环构成

举个for循环的栗子:

1
2
3
4
5
6
>>> a = []
>>> for each in range(5):
... a.append(each)
...
>>> a
[0, 1, 2, 3, 4]

如果用了列表解析式,你可以这样写

a = [each for each in range(5)]

###嵌套

列表解析式支持for循环嵌套,并且在列表操作上比单纯的for循环更加灵活。

【【 元素 子列表解析式】主列表解析式】

假设我们需要创造一个而5x5的棋盘:

使用for循环并不是那么轻松简单;

1
2
3
4
5
6
7
>>> board = []
>>> for row in range(5):
... board.append([])
... for col in range(5):
... board[row].append('+')
>>> board
[['+', '+', '+', '+', '+'], ['+', '+', '+', '+', '+'], ['+', '+', '+', '+', '+'], ['+', '+', '+', '+', '+'], ['+', '+', '+', '+', '+']]

注意,如果不太了解python而为数组但有C的经验的话,很可能会写出下面的代码

1
2
3
4
5
6
7
8
	for row in range(5):
for col in range(5):
board[row][col] = '+'
```
然而这是不对的,python你并不支持通过定点赋值的方法添加新的列表元素,所以代码显得很臃肿。然而此时你已经掌握了列表解析式的嵌套

```Python
>>>board = [['+' for col in range(5)] for row in range(5)]

现在你变得更pythonic(懒)了。

##条件筛选(综合)

如果你想对一个可迭代的对象进行筛选,你就不得不使用for循环来找出每一个子元素并加以判断,大致过程如下:

1
2
3
4
5
6
7
8
9
	for elem in list1:
if condition == True:
list2.append(elem)
```
这样你就可以把所有符合判断条件的list1元素重新组合成新的列表list2中去,举个栗子:

```Python
>>> secretWord = 'apple'
>>> lettersGuessed = ['e', 'i', 'k', 'p', 'r', 's']

使用for循环来找出secretWord中重合的字母

1
2
3
4
5
6
>>> list2 = []
for char in secretWord:
if char in lettersGuessed:
list2.append(char)
>>>list2
['p', 'p', 'e']

忘了告诉你,python中的列表解析式支持条件过滤,格式如下:

[元素 列表解析式 if条件]

有了这个法宝,再回头看我们刚刚的例子

1
2
3
>>> list2 = [each for each in secretWord if each in lettersGuessed]
>>>list2
['p', 'p', 'e']

只要一行,轻轻松松。现在你觉得自己又pythonic(懒)了一分。但是我们现在要做一个猜谜游戏,如果sercretWord中字母不在lettersGuessed 中,我们要用’_‘来表示:(‘_pp_e’).然而列表解析式只支持if条件判断并不支持if…else… 好像阻挡了你pythonic(懒)的脚步,但是这是你突然想起了另一样法宝:

三元表达式,然后你把代码写成了这样

1
list2 = [each for each in secretWord if each in lettersGuessed else '_']

然后就报错了,python告诉你语法错误。知道了列表解析式只支持if条件而不是if..else, 而事实证明确实如此

[元素 列表解析式 if条件]        == **正确**
[元素 列表解析式 if条件else]    == **错误**

这是怎么回事,难道三元表达式和列表解析式真的不能双修吗

其实不然,列表解析式挂载的if条件的方式和与三元表达式结合的方式并不一样,前者在后,后者在前:

1
2
3
>>> list2 = [each if each in lettersGuessed else '_' for each in secretWord]
>>> list2
['_', 'p', 'p', '_', 'e']

真是pythonic(懒)极了。

创建新列表或函数return时,效果极佳。

– End –