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 条评论
登录 后参与评论

相关文章

来自专栏从流域到海域

Python yield关键字 和 Generator(生成器)

Generators functions allow you to declare a function that behaves like an itera...

19210
来自专栏Python爱好者

Java基础笔记04

1535
来自专栏C#

奇妙的NULL值,你知道多少

《NULL值的多义性分析》       谈到NULL值,很多人都是很熟悉,但是深入了解后,又感觉到陌生,对其含义和用法,都无法很准确的理解。NULL在数据库和...

1705
来自专栏顶级程序员

一文读懂Python可迭代对象、迭代器和生成器

序列可以迭代的原因:iter 函数。解释器需要迭代对象 x 时,会自动调用 iter(x)。内置的 iter 函数有以下作用:

933
来自专栏JetpropelledSnake

Python入门之迭代器/生成器/yield的表达方式/面向过程编程

 本章内容     迭代器     面向过程编程       一、什么是迭代       二、什么是迭代器       三、迭代器演示和举例       四、生...

2609
来自专栏微信公众号:Java团长

探究Java虚拟机栈

Java 虚拟机的内存模型分为两部分:一部分是线程共享的,包括 Java 堆和方法区;另一部分是线程私有的,包括虚拟机栈和本地方法栈,以及程序计数器这一小部分内...

532
来自专栏破晓之歌

python 模板实现-引擎的编写(有时间试一下)

1.模板的编写:https://blog.csdn.net/MageeLen/article/details/68920913

803
来自专栏Python中文社区

一文读懂Python可迭代对象、迭代器和生成器

序列可以迭代的原因:iter 函数。解释器需要迭代对象 x 时,会自动调用 iter(x)。内置的 iter 函数有以下作用:

883
来自专栏破晓之歌

JAVA入门1 原

下载地址:http://www.oracle.com/technetwork/java/javase/downloads/jdk9-downloads-3848...

592
来自专栏彭湖湾的编程世界

【javascript/PHP】当一个JavaScripter初次进入PHP的世界,他将看到这样的风景

本文将从以下11点介绍javascript和PHP在基础语法和基本操作上的异同: 1.数据类型的异同 2.常量和变量的定义的不同,字符串连接运算符不同 3.对...

18410

扫描关注云+社区