Python 语法糖之「列表推导式」

2018-06-27 09:07:39 +08:00
 hoxis

Python 基础-列表推导式

https://mp.weixin.qq.com/s?__biz=MjM5NjMyMjUzNg==&mid=2448130614&idx=1&sn=44da08a34a24522ba7ac5f4d39fa379e&chksm=b2f42fb18583a6a7d0e0aee87d3461cddde3c74724fd5d66a26bb9f7331cf3cbcea48521107c&mpshare=1&scene=1&srcid=06258yiaBW1azwu8JL4hk2Us#rd

4087 次点击
所在节点    Python
18 条回复
Geekgogo
2018-06-27 09:36:40 +08:00
给个赞👍
agagega
2018-06-27 09:58:09 +08:00
好像用 map 搞也没什么问题
neoblackcap
2018-06-27 10:03:48 +08:00
列表推导式就不是语法糖,列表推导式的性能比 for-loop 高
kikyous
2018-06-27 10:06:43 +08:00
map/select 才是王道,可是在 python 里面不受待见
xpresslink
2018-06-27 10:08:39 +08:00
x = [i for i in range(10)] => list(range(10))
print([i for i in x if i%2==0]) => print(list(range(0,10,2))


print([i for i in d.keys()]) => print([i for i in d]) or print(list(d.keys()))
print({(j,i) for (i,j) in d.items() }) => print({j:i for i,j in d.items() })

总不能手里拿着锤子看什么都像钉子吧
xpresslink
2018-06-27 10:19:59 +08:00
@kikyous 以前确实是,Python 最初的版本更接近 lisp,只有 map/filter/reduce 方式对序列处理。

后来从 haskell 那里偷师借用的列表推导式,从此开始边缘化 map/filter/reduce 方式。可能是 python 想彻底脱离函数式的风格。

在 python2.x 里用 map 比列表推导式效率高,直到 python3.x 做了优化才稍微超过 map。
Windsooon
2018-06-27 10:41:43 +08:00
支持原创教程,提几个建议。
1. 可迭代对象,其实实现了__iter__方法的对象也是可迭代的,不过文章里面没有提到,容易使人引起误解。
2. 应该写下效率的对比,python2 可以参考[这里]( https://www.python.org/doc/essays/list2str/),python3 用 timeit 就好,告诉读者推导式的效率对比。
3. 4.2 节 for 的嵌套可以讲得更清楚点,很多人遇到嵌套推导都会看不懂。
4. 也讲下列表推导式的缺点吧,常的话可读性差 ,python 源码挺多部分也没有直接用列表推导式。
xpresslink
2018-06-27 10:58:45 +08:00
@Windsooon
for 或 列表推导迭代环境是通过调用内置函数 iter 去尝试__iter__方法来实现的,这种方法返回一个迭代器对象,如果对象实现了,Python 解释器就会重复调用这个迭代器对象的 next 方法,直到发生 StopIteration 异常。
如果没找到这个对象__iter__方法,Python 解释器就会改用__getitem__机制,通过偏移量重复索引,直至发生 IndexError 异常,比如 str 对象是没有__iter__方法的,但是可以被迭代。
lance6716
2018-06-27 11:11:29 +08:00
这叫原创教程?这不就是翻译了翻译官网文档吗
Windsooon
2018-06-27 11:19:13 +08:00
@xpresslink 你说的大部分是正确的,__iter__和__next__会放在一起使用来实现[Iterator Protocol]( https://docs.python.org/3/c-api/iter.html)。但是如果对象的__iter__方法直接返回了一个 iterator 的话,不需要实现__next__方法也可以。
dalang
2018-06-27 11:20:30 +08:00
推荐阅读 https://www.artima.com/weblogs/viewpost.jsp?thread=98196 Guido 一度想在 Python3 里把 map filter reduce 一起都给废掉。
lance6716
2018-06-27 11:32:09 +08:00
@xpresslink 感觉这么说不对。列表表达式在字节码上并没有 FOR_ITER 这一步,是 cpython 在解释器内部实现的
copie
2018-06-27 11:56:53 +08:00
@lance6716 列表表达式确实使用的是 FOR_ITER 生成器表达式使用的字节码和生成器差不多的。
lance6716
2018-06-27 12:03:47 +08:00
@copie 那可能是版本不一样喽,我的是 3.6.4
copie
2018-06-27 12:39:39 +08:00
@lance6716 #14 其实我的版本是 py3.6.5

In [1]: import dis

In [2]: dis.dis("[a for a in [1,23,3]]")
1 0 LOAD_CONST 0 (<code object <listcomp> at 0x7f39be9236f0, file "<dis>", line 1>)
2 LOAD_CONST 1 ('<listcomp>')
4 MAKE_FUNCTION 0
6 LOAD_CONST 5 ((1, 23, 3))
8 GET_ITER
10 CALL_FUNCTION 1
12 RETURN_VALUE

In [3]:
这个应该是你看到的样子。
我们看到 CALL_FUNCTION 运行的就是前面 MAKE_FUNCTION 产生的结果。
然而产生的这个函数的字节码是下面这个样子的所以我说的没有问题。
In [10]: dis.dis(x)
1 0 BUILD_LIST 0
2 LOAD_FAST 0 (.0)
>> 4 FOR_ITER 8 (to 14)
6 STORE_FAST 1 (x)
8 LOAD_FAST 1 (x)
10 LIST_APPEND 2
12 JUMP_ABSOLUTE 4
>> 14 RETURN_VALUE
lolizeppelin
2018-06-27 13:44:02 +08:00
原来这玩意叫列表推倒式

刚开始觉得这玩意不适合阅读.

但是写多了自然而然就用上了.......233
mingyun
2018-06-27 17:57:07 +08:00
[ (x, y) for x in range(10) if x % 2 if x > 3 for y in range(10) if y > 7 if y != 8 ] 这不好阅读吧

{(j,i) for (i,j) in d.items() } 字典也能这样呢 学习了
deepreader
2018-06-28 01:22:51 +08:00
@dalang Map Reduce 在 python 不受待见。但是 Map Reduce 是很好的并行编程模式,用 PySpark 吧

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/466147

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX