Loading...
墨滴

瀋凣

2021/10/04  阅读:51  主题:极简黑

python笔记19

Python day19

1. 列表推导式

回想一下我们在第16课时提到的一个创建二维列表的错误方法:

>>> a = [[0] * 3] * 3
>>> a
[[000], [000], [000]]
>>> a[1][1] = 1
>>> a
[[010], [010], [010]]

看起来非常优雅但是禁不起推敲,所以我们不得已只能去写笨笨的for循环:

>>> b = [0] * 3
>>> for i in range(3):
        b[i] = [0] * 3
        
>>> b
[[000], [000], [000]]
>>> b[1][1] = 1
>>> b
[[000], [010], [000]]

那么有没有一种更加优雅的方法来创建二维列表呢?

您好,有的
通过列表推导式我们可以以一种非常优雅的方式实现上述需求。

>>> c = [[0] * 3 for i in range(3)]
>>> c
[[000], [000], [000]]
>>> c[1][1] = 1
>>> c
[[000], [010], [000]]

非常优雅~

1.2 语法(2)

上节课我们讲的列表推导式语法并不是它的完全体,它的后面还可以添加一个用于筛选的if分句

[表达式 for 变量 in 序列或迭代对象 if 条件]

1.2.1 举个栗子

创建一个在0~9范围内的偶数列表:

>>> even = [i for i in range(10if i % 2 == 0]
>>> even
[02468]

for循环实现:

>>> even = []
>>> for i in range(10):
        if i % 2 == 0:
            even.append(i)
            
>>> even
[02468]

思考
有一个列表,里面是雨果维文的电影《V字仇杀队》的经典台词:

>>> words = ['Voilà','In','View','a','humble','Vaudevillian','Veteran','cast',
'Vicariously','as','both','Victim','and','Villain','by','the','Vicissitudes','of',
'fate','This','Visage','no','mere''Veneer''of''Vanity','is',  'Vestige''of',
'the''Vox''populi''now''Vacant''Vanished''However''this''Valorous',
'Visitation''of''a''by-gone''Vexation''stands''Vivified''and','has'
'Vowed''to''Vanquish''these''Venal''and''Virulent''Vermin''Vanguarding',
'Vice''and''Vouchsafing''the''Violently''Vicious''and''Voracious'
'Violation''of''Volition''The''only''Verdict''is''Vengeance''a''Vendetta',
'held''as''a''Votive''not''in''Vain''for''the''Value''and''Veracity'
'of''such''shall''one''day''Vindicate''the''Vigilant''and''the'
'Virtuous''Verily''this''Vichyssoise''of''Verbiage''Veers''most'
'Verbose''So''let''me','simply''add''that''It''Is''my''Very'
'good''honor''to''meet''you''and''you''may''call''me''V']

现在要从列表words里面筛选出以 “V” 开头的单词,存入新列表v_words

>>> v_words = [i for i in words if i[0] == 'V']
>>> v_words
['View''Vaudevillian''Veteran''Vicariously''Victim''Villain''Vicissitudes'
'Visage''Veneer''Vanity''Vestige''Vox''Vacant''Vanished''Valorous'
'Visitation''Vexation''Vivified''Vowed''Vanquish''Venal''Virulent''Vermin'
'Vanguarding''Vice''Vouchsafing''Violently''Vicious''Voracious''Violation',
'Volition''Verdict''Vengeance''Vendetta''Votive''Vain''Value''Veracity',
'Vindicate''Vigilant''Virtuous''Verily''Vichyssoise''Verbiage''Veers',
'Verbose''Very''V']

for循环实现:

>>> v_words = []
>>> for i in words:
        if i[0] == "V":
            v_words.append(i)

1.3 语法(3)

列表推导式其实还可以变得更加的复杂,那就是实现嵌套:

[表达式 for 变量 in 序列或迭代对象1
       for 变量 in 序列或迭代对象2
       for 变量 in 序列或迭代对象3
                    ···
       for 变量 in 序列或迭代对象n]

嵌套的列表推导式对应的是嵌套的循环。

1.3.1 举个栗子

有一个二维列表:

>>> matrix = [[123], [456], [789]]

将它降维为一个一维列表:

>>> flatten = [123456789]

我们可以这么做:

>>> flatten = [col for row in matrix for col in row]
>>> flatten
[123456789]

想要理解列表推导式的嵌套,只需要将其转化为循环实现就清楚了:

>>> flatten = []
>>> for row in matrix:
        for col in row:
            flatten.append(col)
            
>>> flatten
[123456789]

1.4 语法(4)

终极语法:每个for语句的嵌套都可以带一个if语句用于筛选

[表达式 for 变量 in 序列或迭代对象1 if 条件1
       for 变量 in 序列或迭代对象2 if 条件2
       for 变量 in 序列或迭代对象3 if 条件3
                    ···
       for 变量 in 序列或迭代对象n if 条件n]

1.4.1 举个栗子

>>> [[x, y] for x in range(10if x % 2 == 0 for y in range(10if y % 3 == 0]
[[00], [03], [06], [09], [20], [23], [26], [29], [40], 
[43], [46], [49], [60], [63], [66], [69], [80], [83], 
[86], [89]]

for循环实现:

>>> _ = []
>>> for x in range(10):
        if x % 2 == 0:
            for y in range(10):
                if y % 3 == 0:
                    _.append([x,y])
                    
>>> _
[[00], [03], [06], [09], [20], [23], [26], [29], [40], 
[43], [46], [49], [60], [63], [66], [69], [80], [83], 
[86], [89]]

1.5 “KISS” 原则

列表推导式进行到这里,我们发现它的语法已经变得非常的复杂。只要我们想,我们就可以写一个循环嵌套几十层的列表推导式来实现我们的需求;
但是这样的代码你的同事或同学看得懂吗?或者说三个月后的自己重新打开这个代码,还能看得懂吗?

所以,在以后的学习和工作中,我们编写的程序都应当遵守 KISS 原则;
即:“Keep It Simple and Stupid”(保持简单和傻瓜化)

我们之前就有提到过:“编程的目的是为了更好地解决问题,而不是炫耀精巧但晦涩的语法。” 虽然列表推导式可以使代码变得非常简洁优雅,一行代码解决所有问题,并且运行效率也比传统循环语句要高;但是由于使用了过于复杂的列表推导式,导致代码的可读性变得很差,后期维护成本也随之提高,可谓得不偿失。

建议

当列表推导式的代码超过了两行,就要考虑改成用for循环了。通常的原则是:只用列表推导式来创建新的列表,并且尽量 保持简短

点点关注不迷路
点点关注不迷路
- END -

瀋凣

2021/10/04  阅读:51  主题:极简黑

作者介绍

瀋凣