高级语法

除了像上面介绍的 [x ** 2 for x in L] 这种基本语法之外,列表推导式还有一些高级的扩展。

4.1. 带有if语句

我们可以在 for 语句后面跟上一个 if 判断语句,用于过滤掉那些不满足条件的结果项。

例如,我想去除列表中所有的偶数项,保留奇数项,可以这么写:

>>> L = [1, 2, 3, 4, 5, 6]
>>> L = [x for x in L if x % 2 != 0]
>>> L
[1, 3, 5]

4.2. 带有for嵌套

在复杂一点的列表推导式中,可以嵌套有多个 for 语句。按照从左至右的顺序,分别是外层循环到内层循环。

例如:

>>> [x + y for x in 'ab' for y in 'jk']
['aj', 'ak', 'bj', 'bk']

4.3. 既有if语句又有for嵌套

列表推导式可以带任意数量的嵌套 for 循环,并且每一个 for 循环后面都有可选的 if 语句。

通用语法:

[ expression for x in X [if condition]
for y in Y [if condition]
...
for n in N [if condition] ]

例如,下面的代码输出了0~4之间的偶数和奇数的组合。

>>> [(x, y) for x in range(5) if x % 2 == 0 for y in range(5) if y % 2 == 1]
[(0, 1), (0, 3), (2, 1), (2, 3), (4, 1), (4, 3)]

等价于下面的一般 for 循环:

>>> L = []
>>> for x in range(5):
... if x % 2 == 0:
... for y in range(5):
... if y % 2 == 1:
... L.append((x, y))
>>> L
[(0, 1), (0, 3), (2, 1), (2, 3), (4, 1), (4, 3)]

4.4. 列表推导式生成矩阵

生成矩阵的方式有多种,例如手动赋值、一般for循环,还有就是列表推导式。如果我们要用列表推导式生成下面的矩阵,可以怎么写?

>>> M = [[1, 2, 3],
... [4, 5, 6],
... [7, 8, 9]]

一种方法是:

>>> M = [[x, x+1, x+2] for x in [1, 4, 7]]
>>> M
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]

矩阵的列数少时可以使用这种方法。

如果矩阵的列数较多,我们可以使用另外一种方式:在循环变量的表达式中使用列表推导式。

具体代码如下:

>>> M = [[y for y in range(x, x+3)] for x in [1, 4, 7]]
>>> M
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]

与之前带 for 嵌套的语法不同,这个例子中,实际使用的是最基本的 [expression for x in L] 语法,只有一个 for 语句。

复杂的地方在于前面的变量表达式 expression 不再是简单的变量运算,而是一个列表推导式,在这个例子中就是 [y for y in range(x, x+3)]
内层的列表推导式返回一个行向量,而这些行向量经由外层的列表推导式,最终形成一个二维列表,也就是我们想要的矩阵。

当然,在实际的应用中不能单纯追求代码的简洁,还要考虑到代码的可读性和维护成本。
如果代码变得过于复杂,不易于理解,我们宁可多写几行代码来增加它的可读性。

5. 生成器表达式

生成器表达式与列表推导式的语法相同,区别在于生成器表达式的外面使用圆括号,而列表推导式使用方括号。

有关生成器的介绍,请参考这篇文章:《Python高级编程之初识生成器》

6. 集合推导式和字典推导式

注意:集合推导式和字典推导式只有在Python2.7以及之后的版本中才有,Python2.7之前的版本不支持这两种推导式。

集合推导式的语法与列表推导式相同,只需要把外面的方括号改成花括号即可。

例如,我们可以通过以下方式来生成一个集合:

>>> {x ** 2 for x in [1, 2, 2]}
{1, 4}

字典推导式的外面也是使用花括号,不过花括号的内部需要包含键值两部分。

在值不重复的情况下,我们可以通过字典推导式快速交换键值对:

>>> D = {'a':1, 'b':2, 'c':3}
>>> D = {value: key for key, value in D.items()}
>>> D
{1: 'a', 2: 'b', 3: 'c'}

from:http://www.codebelief.com/article/2017/02/python-advanced-programming-list-comprehensions/


lix = [];
for x in range(1, 101):
lix.push(x ** 2)
执行结果:lix = [1,4,9,16,25.....]

在列表构建器的表达式中,可以添加简单的条件处理

lix = [x * x for x in range(1, 101) if x % 2 == 0]
执行结果:lix = [4,16,36.....]

也可以在循环过程中,来使用多层循环嵌套,实现更加复杂的效果

lix = [x + y  for x in "abc" for y in "xyz"]
执行结果:['ax', 'ay', 'az', 'bx', 'by', 'bz', 'cx', 'cy', 'cz']

列表动态构建器

但是我们通过前面的学习已经知道,这些数据都是加载到内存中的,如果列表中的数据量比较大的情况下,内存消耗是比较严重的
在某些情况下,我们只需要使用列表中的一部分数据,后面的数据并不是特别关心,如:通过列表来记录一个符合某种规则的序列,每次我们只是关心下一个数据,并不关心后面的N条数据,应该怎么做呢?比如我们需要一个奇数列表

# 常规构建器的做法
lix = [2*x + 1 for x in range(1, 101)]
# 执行结果:[1,3,5,7,9,11,13,15,17.....]
# * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
# 常规构建器可以直接构建生成
# 但是存在问题,如果一次构建的数据量太大,会严重占用内存
# 我们在使用该列表的时候,有可能只是使用前10项
# * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
# 使用列表动态构建器
lix = (2 * x - 1 for x in range(1, 101))
# 执行结果:print (lix) --> <generator object <genexpr> at 0x7f232e462048>
next(lix)
# 执行结果:1
next(lix)
# 执行结果:3
next(lix)
# 执行结果:5
next(lix)
# 执行结果:7
# * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
# 列表动态构建器
# 和构建器基本没有区别,创建的时候列表中是没有数据的
# 必须通过next()函数来获取列表中的下一条数据
# * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

from:https://www.jianshu.com/p/fa3fda487f15

 
 

[]改成(),就创建了一个generator:

>>> L = [x * x for x in range(10)]
>>> L
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
>>> g = (x * x for x in range(10))
>>> g
<generator object <genexpr> at 0x1022ef630>

L和g的区别仅在于最外层的[]()L是一个list,而g是一个generator。

如果要一个一个打印出来,可以通过next()函数获得generator的下一个返回值:

>>> next(g)
0
>>> next(g)
1
>>> next(g)
4
>>> next(g)
9
>>> next(g)

next(g)实在是太变态了,正确的方法是使用for循环,因为generator也是可迭代对象:

>>> g = (x * x for x in range(10))
>>> for n in g:
... print(n)
...
0
1
4
9
要把fib函数变成generator,只需要把print(b)改为yield b就可以了:
def fib(max):
n, a, b = 0, 0, 1
while n < max:
yield b
a, b = b, a + b
n = n + 1
return 'done'

yield关键字,那么这个函数就不再是一个普通函数,而是一个generator:

>>> f = fib(6)
>>> f
<generator object fib at 0x104feaaa0>

return语句或者最后一行函数语句就返回。而变成generator的函数,在每次调用next()的时候执行,遇到yield语句返回,再次执行时从上次返回的yield语句处继续执行。

 

python 循环高级用法 [expression for x in X [if condition] for y in Y [if condition] ... for n in N [if condition] ]按照从左至右的顺序,分别是外层循环到内层循环的更多相关文章

  1. python requests 高级用法

    高级用法 本篇文档涵盖了 Requests 的一些高级特性. 会话对象 会话对象让你能够跨请求保持某些参数.它也会在同一个 Session 实例发出的所有请求之间保持 cookie, 期间使用 url ...

  2. Python pip高级用法

    1.pip 高级用法为了便于用户安装和管理第三方库和软件,越来越多的编程语言拥有自己的包管理工 具,如 nodejs 的 npm, ruby 的 gem. Python 也不例外,现在 Python ...

  3. Volocity循环高级用法

    #foreach($announcementDo in $announcementList) #set($listSize=$!announcementList.size() - 1) #if(($v ...

  4. (转)python requests 高级用法 -- 包括SSL 证书错误的解决方案

    我在使用requests访问某个https网站时出现错误  error::SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify fai ...

  5. python requests 高级用法 -- 包括SSL 证书错误的解决方案

    Session Objects会话对象 Session对象在请求时允许你坚持一定的参数.此外,还坚持由Session实例的所有请求的cookie. 让我们坚持在请求时使用 s = requests.S ...

  6. Python sqlalchemy 高级用法

    一. 关联查询 sys_user_list = SysPermission.query.join(OrgRolePermission, OrgRolePermission.sys_permission ...

  7. python核心高级学习总结7---------正则表达式

    正则表达式在爬虫项目中应用很广泛,主要方面就是在字符串处理方面,经常会涉及到字符串格式的校验,用起来经常要查看文档才能完成,所以抽了个时间将正则的内容复习了一下. Start re---导入re模块使 ...

  8. 四年级--python函数基础用法

    一.函数的定义,调用和返回值 1.1 语法 def 函数(参数一,参数二...): ''' 文档注释 ''' 代码逻辑一 代码逻辑二 .... return 返回值 1.2 定义函数的三种形式 说明: ...

  9. Python内建函数enumerate()用法及在for循环应用

    Python 内建函数enumerate() 由于这个单纯很长,不容易记住,用法还是比较广泛的,下面讲述Python内建函数enumerate()用法. 1,实例 enumerate(sequence ...

随机推荐

  1. Xamarin View获取属性的绑定信息

    public static Binding GetBinding( BindableObject self, BindableProperty property) { var methodInfo = ...

  2. ORB-SLAM2:一种开源的VSLAM方案(译文)

    摘要: ORB-SLAM2是基于单目,双目和RGB-D相机的一套完整的SLAM方案.它能够实现地图重用,回环检测和重新定位的功能.无论是在室内的小型手持设备,还是到工厂环境的无人机和城市里驾驶的汽车, ...

  3. js一般用法

    <1> 通过id查找html元素 var x=document.getElementById("intro");   <2> 通过标签名查找html元素 v ...

  4. php部分基础

    变量使用$,如$num = 1; 或 $name = 'hey'; 创建数组:$arr = array('a','b','c'); 或 $arr = array('a' => $name); 取 ...

  5. java代码完全手写模仿qq登录界面

    这是我模仿QQ2015版界面,实现的基本功能有登陆验证,重置等,当然直接复制代码运行是不一样的,还要注意自己插入自己的图片. 结果截图如下所示: import java.awt.BorderLayou ...

  6. php第三十节课

    文件操作 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3 ...

  7. 「 hihoCoder 1014 」Trie 树

    标题真直接 题目大意 给你 $n$ 个字符串.存到一个字典中.又给你 $m$ 个询问,每个询问给一个字符串,在字典中查出有多少个字符串是以这个字符串为前缀. 解题思路 模板题啊 在每个点设置一个变量 ...

  8. out对象的使用

    out对象的使用 制作人:全心全意 out对象用于在Web浏览器内输出信息,并且管理应用服务器上的输出缓冲区.在使用out对象输出数据时,可以对数据缓冲区进行操作,及时清除缓冲区中的残余数据,为其他的 ...

  9. svn汉化包安装无效的解决办法

    下载svn汉化包要和对应的svn客户端版本对应,否则安装无效, 在安装前要想将svn安装目录下的languages目录下的文件全部删除 还有一点要注意的是 汉化包安装要放在svn安装目录下进行安装,它 ...

  10. day21 01 包的初识

    day21 01包的初识 包:把解决一类问题的模块放在同一个文件夹里面-----包(一个包里面通常会含有_init_.py文件(python2里面必须有),但是后面的就没有要求一定要有了) 同样导入的 ...