ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Python解析式

Python解析式 在日常的情况里面, 是经常可以看见形如ret等于的这种表现的。这是一个列表推导式, 用于计算列表中每个元素的平方。这类赋值语句, 对于从C转行过来的人来说, 不是太容易懂得这种for循环的用法是怎么一回事, 这也就是为了追求简练而被创造出来的一种新式语法。解析式存在如下的一些好处:该解析式被明确地划分成下述的四种具体情形。接下来会一个一个地说说这四种表达方式该怎么用。In [1]: lst range(10)In [2]: %%timeit...: ret [x ** 2 for x in lst]...:100000 loops, best of 3: 5.28 µs per loopIn [3]: %%timeit...: ret []...: for x in lst:...: ret.append(x ** 2)...:100000 loops, best of 3: 6.09 µs per loop # 耗时稍高可以发现运行效率是稍微高出了一点, 但是最主要的优势还是在于代码的简洁性。你可以把列表解析式和if语句搭配在一起用。比如,从列表lst里面把偶数给挑出来。In [4]: ret []In [5]: for x in lst:...: if x % 2 0:...: ret.append(x) # 使用for循环...:In [6]: retOut[6]: [0, 2, 4, 6, 8]In [7]: ret [x for x in lst if x % 2 0] # 使用列表解析式In [8]: retOut[8]: [0, 2, 4, 6, 8]列表解析式是能够像for循环那样来使用if语句的。在列表解析式的for语句部分, 是能够去实现嵌套操作的。In [9]: (x, y) for x in range(0, 5) for y in range(5, 10)File , line 1(x, y) for x in range(0, 5) for y in range(5, 10)^SyntaxError: invalid syntax# 说明列表解析式一定要使用中括号括起来In [10]: [(x, y) for x in range(5) for y in range(5, 10)]Out[10]:[(0, 5),(0, 6),(0, 7),(0, 8),(0, 9),(1, 5),(1, 6),(1, 7),(1, 8),(1, 9),(2, 5),(2, 6),(2, 7),(2, 8),(2, 9),(3, 5),(3, 6),(3, 7),(3, 8),(3, 9),(4, 5),(4, 6),(4, 7),(4, 8),(4, 9)]In [11]: ret []In [12]: for x in range(5):...: for y in range(5, 10):...: ret.append((x, y))...:In [13]: retOut[13]:[(0, 5),(0, 6),(0, 7),(0, 8),(0, 9),(1, 5),(1, 6),(1, 7),(1, 8),(1, 9),(2, 5),(2, 6),(2, 7),(2, 8),(2, 9),(3, 5),(3, 6),(3, 7),(3, 8),(3, 9),(4, 5),(4, 6),(4, 7),(4, 8),(4, 9)]单行if语句的写法, 和列表解析式的写法, 看起来是非常相似的。这是三目运算符的表达式形式, 也可以写成x如果cond就输出y否则的样子。下面进行演示, 这种演示以具体的例子为依托, 具体来说是把偶数拿来进行平方运算操作, 而把奇数拿来进行立方运算操作。In [14]: ret []In [15]: for x in lst:...: if x % 2 0:...: ret.append(x ** 2)...: else:...: ret.append(x ** 3)...:In [16]: retOut[16]: [0, 1, 4, 27, 16, 125, 36, 343, 64, 729]In [17]: x 3# if特殊用法In [18]: x ** 2 if x % 2 0 else x ** 3Out[18]: 27In [19]: 3 if True else 4Out[19]: 3# 如果采用if特殊用法配合列表解析式 x if cond else y for ...In [20]: [x ** 2 if x % 2 0 else x ** 3 for x in lst]Out[20]: [0, 1, 4, 27, 16, 125, 36, 343, 64, 729]生成器解析式当人们看到列表解析式, 它会直接返回一个具体的列表, 而生成器解析式的用途不同, 它能够产生的结果叫做解析式内容, 如果使用者把列表解析式外面的中括号改换成小括号, 那么得到的东西就是生成器解析式。In [1]: range(10000)Out[1]: range(0, 10000)In [2]: g (x ** 2 for x in range(100000000000))In [3]: gOut[3]: at 0x7f9f08a5f0a0gt;In [4]: next(g)Out[4]: 0In [5]: next(g)Out[5]: 1In [6]: next(g)Out[6]: 4列表解析式和生成器解析式的选择如果把这个列表解析式里边的中括号给换掉, 换成那种大括号的话, 这就变成集合解析式了。In [1]: lst [2, 4, 5, 6, 3, 4, 2]In [2]: s {x for x in lst}In [3]: sOut[3]: {2, 3, 4, 5, 6} # 可见列表解析式生成的时候会去掉重复符合集合要求In [4]: type(s)Out[4]: set在利用语法的时候会发现使用字典解析式同样也需要大括号, 可是需要搞清楚的是与集合解析式的区别在于对于表达式的位置而言并不是单个元素, 而是把键和值组成的对进行放置。In [1]: {str(x): x for x in range(5)}Out[1]: {0: 0, 1: 1, 2: 2, 3: 3, 4: 4}在这四种解析式里, 被用得最广的还要属那个列表解析式。平时大家经常会碰到一些让人叫绝的、特别巧妙的用法情况。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进