V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
hoxis
V2EX  ›  Python

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

  •  
  •   hoxis · 2018-06-27 09:07:39 +08:00 · 4136 次点击
    这是一个创建于 2376 天前的主题,其中的信息可能已经有所发展或是发生改变。
    18 条回复    2018-06-28 01:22:51 +08:00
    Geekgogo
        1
    Geekgogo  
       2018-06-27 09:36:40 +08:00
    给个赞👍
    agagega
        2
    agagega  
       2018-06-27 09:58:09 +08:00
    好像用 map 搞也没什么问题
    neoblackcap
        3
    neoblackcap  
       2018-06-27 10:03:48 +08:00
    列表推导式就不是语法糖,列表推导式的性能比 for-loop 高
    kikyous
        4
    kikyous  
       2018-06-27 10:06:43 +08:00
    map/select 才是王道,可是在 python 里面不受待见
    xpresslink
        5
    xpresslink  
       2018-06-27 10:08:39 +08:00   ❤️ 1
    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
        6
    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
        7
    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
        8
    xpresslink  
       2018-06-27 10:58:45 +08:00
    @Windsooon
    for 或 列表推导迭代环境是通过调用内置函数 iter 去尝试__iter__方法来实现的,这种方法返回一个迭代器对象,如果对象实现了,Python 解释器就会重复调用这个迭代器对象的 next 方法,直到发生 StopIteration 异常。
    如果没找到这个对象__iter__方法,Python 解释器就会改用__getitem__机制,通过偏移量重复索引,直至发生 IndexError 异常,比如 str 对象是没有__iter__方法的,但是可以被迭代。
    lance6716
        9
    lance6716  
       2018-06-27 11:11:29 +08:00 via Android
    这叫原创教程?这不就是翻译了翻译官网文档吗
    Windsooon
        10
    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
        11
    dalang  
       2018-06-27 11:20:30 +08:00
    推荐阅读 https://www.artima.com/weblogs/viewpost.jsp?thread=98196 Guido 一度想在 Python3 里把 map filter reduce 一起都给废掉。
    lance6716
        12
    lance6716  
       2018-06-27 11:32:09 +08:00
    @xpresslink 感觉这么说不对。列表表达式在字节码上并没有 FOR_ITER 这一步,是 cpython 在解释器内部实现的
    copie
        13
    copie  
       2018-06-27 11:56:53 +08:00 via Android
    @lance6716 列表表达式确实使用的是 FOR_ITER 生成器表达式使用的字节码和生成器差不多的。
    lance6716
        14
    lance6716  
       2018-06-27 12:03:47 +08:00
    @copie 那可能是版本不一样喽,我的是 3.6.4
    copie
        15
    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
        16
    lolizeppelin  
       2018-06-27 13:44:02 +08:00
    原来这玩意叫列表推倒式

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

    但是写多了自然而然就用上了.......233
    mingyun
        17
    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
        18
    deepreader  
       2018-06-28 01:22:51 +08:00
    @dalang Map Reduce 在 python 不受待见。但是 Map Reduce 是很好的并行编程模式,用 PySpark 吧
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1253 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 18:01 · PVG 02:01 · LAX 10:01 · JFK 13:01
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.