Python之解析式您知多少?

解析式 解析式 今天给大家介绍Python中的解析式。

解析式简单介绍

解析式,

  1. 列表解析 # Python2只有列表解析
  2. 生成器解析 # Python3特有
  3. 集合解析 # Python3特有
  4. 字典解析 # Python3特有

解析式的作用:

  1. 修改可迭代对象
  2. 过滤可迭代对象

zip方法:

In[1]: help(zip)

Help on class zip in module builtins:

class zip(object)
|  zip(iter1 [,iter2 [...]]) --> zip object
|  
|  Return a zip object whose .__next__() method returns a tuple where
|  the i-th element comes from the i-th iterable argument.  The .__next__()
|  method continues until the shortest iterable in the argument sequence
|  is exhausted and then it raises StopIteration.

In[3]: list(zip(range(10), range(10)))
Out[3]: 
[(0, 0),
(1, 1),
(2, 2),
(3, 3),
(4, 4),
(5, 5),
(6, 6),
(7, 7),
(8, 8),
(9, 9)]

In[4]: {x:y for x, y in zip(range(10), range(10))}
Out[4]: {0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9}

In[5]: list(zip(range(5), range(10), range(20)))
Out[5]: [(0, 0, 0), (1, 1, 1), (2, 2, 2), (3, 3, 3), (4, 4, 4)]

zip方法用于合并多个可迭代对象,合并后的长度等于最短的可迭代对象的长度。

每种解析式都可以翻译为for循环。为什么没有元组解析?

列表解析

列表解析式示例

列表解析的一般形式:

[expression for item in iterable]

接下来看几个示例:

In[23]: [2 ** n for n in range(10)]
Out[23]: [1, 2, 4, 8, 16, 32, 64, 128, 256, 512]

In[24]: def inc(x):
    ...:     return x + 1
    ...: 

In[25]: [inc(x) for x in range(10)]
Out[25]: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

In[26]: [0 for x in range(10)]
Out[26]: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

In[27]: def non_return(x):
    ...:     pass
    ...: 

In[28]: [non_return(x) for x in range(10)]
Out[28]: [None, None, None, None, None, None, None, None, None, None]

列表解析式返回的结果是列表,列表的内容是表达式执行的结果。接着看例子:

In[13]: [x for x in range(10) if x % 2 == 0]
Out[13]: [0, 2, 4, 6, 8]

# 上面的语句等效于
ret = []
for x in range(10):
    if x % 2 == 0:
        ret.append(x)
# 可以使用ipython的timeit来测试两种方式的执行效率。
# 列表解析的执行效率会好一些

列表解析式中带有if关键字

如果列表解析式中有if关键字呢:

[exper for item in iterable if cond]
# 等价于
ret = []
for item in iterable:
    if cond:
        ret.append(exper)

以上介绍的只带了一个if关键字,如果有多个if关键字呢:

[exper for item in iterable if cond1 if cond2]
# 等价于
ret = []
for item in iterable:
    if cond1:
        if cond2:
            ret.append(exper)

针对上面来个例子:

[x for x in range(10) if x % 2 == 0 if x > 1]
[2, 4, 6, 8]

# 再来个例子
lst = [[0, 1], [1, 2], [2, 3], [3, 4], [4]]
[x for x in lst if len(x) > 1 and x.pop(0) % 2 == 0]

不但可以有多个if关键字,还可以有多个for关键字:

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

写成一个公式类的写法为:

[expr for item1 in iterable1 for item2 in iterable2]
# 等价于
ret = []
for item1 in iterable1:
    for item2 in iterable2:
        ret.append(expr)

那么for与if都有呢?多个for语句相当于逐层for嵌套。

# 逐层嵌套
In[11]: [(x, y) for x in range(10) for y in range(10) if (x+y) % 2 == 0]
Out[11]: 
[(0, 0),
 (0, 2),
 (0, 4),
 (0, 6),
 (0, 8),
 (1, 1),
 (1, 3),
 (1, 5),
 (1, 7),
 (1, 9),
 (2, 0),
 (2, 2),
 (2, 4),
 (2, 6),
 (2, 8),
 (3, 1),
 (3, 3),
 (3, 5),
 (3, 7),
 (3, 9),
 (4, 0),
 (4, 2),
 (4, 4),
 (4, 6),
 (4, 8),
 (5, 1),
 (5, 3),
 (5, 5),
 (5, 7),
 (5, 9),
 (6, 0),
 (6, 2),
 (6, 4),
 (6, 6),
 (6, 8),
 (7, 1),
 (7, 3),
 (7, 5),
 (7, 7),
 (7, 9),
 (8, 0),
 (8, 2),
 (8, 4),
 (8, 6),
 (8, 8),
 (9, 1),
 (9, 3),
 (9, 5),
 (9, 7),
 (9, 9)]

[(x, y) for x in range(10) if x % 2 == 0 for y in range(10)]
# 等价于
ret = []
for x in range(10):
    if x % 2 == 0:
        for y in range(10):
            ret.append((x, y))

# 如果for关键字不在第一个位置,会不会出问题呢
In[12]: [x if True for x in range(10)]
  File "<ipython-input-12-c9daacf14b27>", line 1
    [x if True for x in range(10)]
                 ^
SyntaxError: invalid syntax

# 因此,for关键字要写在前面,后面可以用for或if进行嵌套

多看几个例子吧:

In[9]: [(x+1, x+2) for x in range(5)]
Out[9]: [(1, 2), (2, 3), (3, 4), (4, 5), (5, 6)]

In[10]: [{x+1:x+2} for x in range(5)]
Out[10]: [{1: 2}, {2: 3}, {3: 4}, {4: 5}, {5: 6}]

列表解析用于可迭代对象做过滤和转换,返回值是列表。

help(filter)

filter(lambda x: x % 2 == 0, range(10))

list(filter(lambda x: x % 2 == 0, range(10)))

help(map)
list(map(lambda x: x+1, range(10)))

[x+1 for x in range(10)]

# Python里,可以不用filter及map函数,使用列表解析式可以秒杀filter及map
# 上面的话并不是绝对的,当数据比较大时,使用filter及map将会比列表解析式快

再来看一个例子,偶数求平方,奇数求立方。

lst = list(range(10))
     [x ** 2 if x % 2 == 0 else x ** 3 for x in lst]

   #+RESULTS:
   | 0 | 1 | 4 | 27 | 16 | 125 | 36 | 343 | 64 | 729 |

总结上述代码:

x if cond else y
当条件满足时返回x,当条件不满足时返回y。

列表解析的一个例子

#!/usr/bin/env python
# coding: utf-8

import time

is_forloop = input('0 is list comprehension, 1 is for loop: ')

min_time = 1000
avg_time = 0.0
run_loops = 1000

for num in range(run_loops):
    start_clock = time.clock()
    if is_forloop:
    a = []
    for x in range(0, 100):
        for y in range(0, 100):
        if x * y > 25:
            a.append((x, y))
    else:
    a = [(x, y) for x in range(100) for y in range(100) if x * y > 25]

    end_clock = time.clock()
    avg_time += end_clock - start_clock
    if (end_clock - start_clock) < min_time:
    min_time = end_clock - start_clock

print "length of result is", len(a)
print run_loops, u"次的最好运行时间为", min_time, 's'
print run_loops, u"次的平均运行时间为", avg_time / run_loops, 's'

列表解析式总结

  1. 使用列表解析式为了让代码更简洁

字典解析

字典解析也需要一个大括号,并且要有两个表达式:一个生成key,一个生成value;两个表达式之间使用冒号分隔,返回结果是字典。

In[14]: {str(x):x for x in range(10)}
Out[14]: 
{'0': 0,
 '1': 1,
 '2': 2,
 '3': 3,
 '4': 4,
 '5': 5,
 '6': 6,
 '7': 7,
 '8': 8,
 '9': 9}

看一个例子:

{str(x):y for x in range(3) for y in range(4)} # 取决于短的那个
{'0': 3, '1': 3, '2': 3}

ret = {}
for x in range(3):
    for y in range(4):
        ret[str(x)] = y
print(ret)

集合解析

集合解析把列表解析的中括号变成大括号,返回集合。

In[45]: {x for x in range(10)}
Out[45]: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}

In[46]: set01 = {x for x in range(10)}

In[47]: set01
Out[47]: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}

In[48]: type(set01)
Out[48]: set

本文总结

今天给大家介绍了几种解析式,分别是:

  1. 列表解析式
  2. 字典解析式
  3. 集合解析式

在前进的路上我们并不孤单,每天都进步一点点,加油!小白甘愿做个知识的搬运工为大家服务。

原文发布于微信公众号 - 小白的技术客栈(XBDJSKZ)

原文发表时间:2017-09-03

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏数据结构与算法

16:忽略大小写的字符串比较

16:忽略大小写的字符串比较 总时间限制: 1000ms 内存限制: 65536kB描述 一般我们用strcmp可比较两个字符串的大小,比较方法为对两个字符串...

3899
来自专栏闪电gogogo的专栏

Python——正则表达式特殊符号及用法

由于正则表达式的内容比较多,所以单独写成一系列文章,主要内容是根据小甲鱼所讲的内容综合一下正则表达式的笔记。 贴上小甲鱼的《Python3 如何优雅地使用正则表...

21510
来自专栏java达人

JSON.stringify(), JSON.parse(), toJSON()方法使用

1 JSON.stringify() 将value(Object,Array,String,Number...)序列化为JSON字符串 即:把原来是对象的类型...

29810
来自专栏机器学习算法与Python学习

python: 函数详解

def square(x): return x**2 >>> square <function square at 0x031AA230> >>> dir(sq...

5137
来自专栏Jerry的SAP技术分享

聊聊JavaScript和Scala的表达式 Expression

函数f的实现,会检查这两个参数的类型,如果是函数,则执行函数调用,再打印其返回值,否则直接打印传入的表达式的值。

872
来自专栏GreenLeaves

JavaScript引用类型之Array数组的toString()和valueof()方法的区别

一、转换方法 1、在JavaScript中几乎所有对象都具有toLocaleString()、toString和valueof()方法,因为,所有的对象都继承自...

2107
来自专栏Java帮帮-微信公众号-技术文章全总结

【选择题】Java基础测试二(15道)

【选择题】Java基础测试二(15道) 11.对于构造方法,下列叙述正确的是:(AC) A. 构造方法的方法名必须与类名相同; B. 构造方法必须用void...

41010
来自专栏Laoqi's Linux运维专列

python3–元祖+列表+字典

3084
来自专栏JavaEE

redis学习之redis基本数据类型前言:数据类型详解:

1143
来自专栏Vamei实验室

Python基础07 函数

函数最重要的目的是方便我们重复使用相同的一段程序。 将一些操作隶属于一个函数,以后你想实现相同的操作的时候,只用调用函数名就可以,而不需要重复敲所有的语句。 函...

2049

扫码关注云+社区

领取腾讯云代金券