19 回复

给个赞👍


列表推导式是Python里处理列表生成和转换的利器,用一行代码就能搞定循环和条件判断。

基本语法是 [expression for item in iterable if condition]
举个例子,生成 0 到 9 的平方列表:

squares = [x**2 for x in range(10)]

加上条件过滤,比如只要偶数的平方:

even_squares = [x**2 for x in range(10) if x % 2 == 0]

嵌套循环也可以写在一起,比如生成坐标对:

coords = [(x, y) for x in range(3) for y in range(2)]

字典和集合也有对应的推导式:

# 字典推导式
square_dict = {x: x**2 for x in range(5)}
# 集合推导式
unique_squares = {x**2 for x in [1, -1, 2]}

注意别滥用复杂的推导式,否则会降低可读性。

一句话建议:用推导式让代码更简洁,但别牺牲可读性。

好像用 map 搞也没什么问题

列表推导式就不是语法糖,列表推导式的性能比 for-loop 高

map/select 才是王道,可是在 python 里面不受待见

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() })

总不能手里拿着锤子看什么都像钉子吧

以前确实是,Python 最初的版本更接近 lisp,只有 map/filter/reduce 方式对序列处理。

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

在 python2.x 里用 map 比列表推导式效率高,直到 python3.x 做了优化才稍微超过 map。

支持原创教程,提几个建议。
1. 可迭代对象,其实实现了__iter__方法的对象也是可迭代的,不过文章里面没有提到,容易使人引起误解。
2. 应该写下效率的对比,python2 可以参考[这里]( https://www.python.org/doc/essays/list2str/),python3 用 timeit 就好,告诉读者推导式的效率对比。
3. 4.2 节 for 的嵌套可以讲得更清楚点,很多人遇到嵌套推导都会看不懂。
4. 也讲下列表推导式的缺点吧,常的话可读性差 ,python 源码挺多部分也没有直接用列表推导式。


for 或 列表推导迭代环境是通过调用内置函数 iter 去尝试__iter__方法来实现的,这种方法返回一个迭代器对象,如果对象实现了,Python 解释器就会重复调用这个迭代器对象的 next 方法,直到发生 StopIteration 异常。
如果没找到这个对象__iter__方法,Python 解释器就会改用__getitem__机制,通过偏移量重复索引,直至发生 IndexError 异常,比如 str 对象是没有__iter__方法的,但是可以被迭代。

这叫原创教程?这不就是翻译了翻译官网文档吗

你说的大部分是正确的,__iter__和__next__会放在一起使用来实现[Iterator Protocol]( https://docs.python.org/3/c-api/iter.html)。但是如果对象的__iter__方法直接返回了一个 iterator 的话,不需要实现__next__方法也可以。

推荐阅读 https://www.artima.com/weblogs/viewpost.jsp?thread=98196 Guido 一度想在 Python3 里把 map filter reduce 一起都给废掉。

感觉这么说不对。列表表达式在字节码上并没有 FOR_ITER 这一步,是 cpython 在解释器内部实现的

列表表达式确实使用的是 FOR_ITER 生成器表达式使用的字节码和生成器差不多的。

那可能是版本不一样喽,我的是 3.6.4

#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

原来这玩意叫列表推倒式

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

但是写多了自然而然就用上了…233

[ (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() } 字典也能这样呢 学习了

Map Reduce 在 python 不受待见。但是 Map Reduce 是很好的并行编程模式,用 PySpark 吧

回到顶部