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
Jeepeng
V2EX  ›  Python

新手求问,关于 lambda 表达式问题

  •  
  •   Jeepeng · 2017-09-22 11:37:33 +08:00 · 3642 次点击
    这是一个创建于 2619 天前的主题,其中的信息可能已经有所发展或是发生改变。
    #!/usr/bin/env python3
    # -*- coding: utf-8 -*-
    
    def main():
        for n in primes():
            if n < 100:
                print(n)
            else:
                break
    
    def _odd_iter():
        n = 1
        while True:
            n = n + 2
            yield n
    
    def _not_divisible(n):
        return lambda x: x % n > 0
    
    def primes():
        yield 2
        it = _odd_iter()
        while True:
            n = next(it)
            yield n
            it = filter(_not_divisible(n), it)
    
    if __name__ == '__main__':
        main()
    

    如果将

    it = filter(_not_divisible(n), it)
    

    改成

    it = filter(lambda x: x % n > 0, it)
    

    两次结果不一样,是 n 的作用域问题? filter 惰性求值问题?

    14 条回复    2017-09-22 23:25:52 +08:00
    rwdy2008
        1
    rwdy2008  
       2017-09-22 15:33:41 +08:00
    首先说明下,题主的代码参数有点问题哦

    其次,
    _not_divisible 函数你这样写返回时的一个 function,function 永远是 True
    直接写 lambda 返回的是 True 或者 False

    filter 内置函数对 True 结果处理,这应该就是问题所在

    最后,
    看下面代码,题主参考下应该就明白了

    def _not_divisible(n):
    return lambda x: x % 3 > 0

    filter(_not_divisible, [5,6])
    [5, 6]

    _not_divisible(5)
    <function <lambda> at 0x036DAA30>
    _not_divisible(6)
    <function <lambda> at 0x036F82F0>

    上面这两个都返回的是 function

    filter(lambda x: x % 3 > 0, [5,6])
    [5]

    f = lambda x: x % 3 > 0
    filter(f, [5,6])
    [5]

    f(5)
    True
    f(6)
    False

    这个有 False 返回

    题主明白了吗?
    rwdy2008
        2
    rwdy2008  
       2017-09-22 15:34:36 +08:00
    回复里不会贴代码,看起来有点乱,将就看吧,微笑脸
    ballshapesdsd
        3
    ballshapesdsd  
       2017-09-22 16:47:45 +08:00
    @rwdy2008 你看错了
    用了 python 好多年了,我也搞不懂,坐等高手,我感觉是不是跟下面这个有关:
    1:
    for i in range(5):
    f=lambda x:x+i
    i=5
    print f(1)
    output:
    6
    6
    6
    6
    6

    2:
    def aaa(n):
    return lambda x:x+n

    for i in range(5):
    f=aaa(i)
    i=5
    print f(1)
    output:
    1
    2
    3
    4
    5
    ballshapesdsd
        4
    ballshapesdsd  
       2017-09-22 17:06:29 +08:00
    我觉得有可能是这样子的:
    如果用 it = filter(lambda x: x % n > 0, it)的话,在使用 next(it)的时候,才会去找当前的 n,不管你之前过滤了多少次,等于用当前的 n 过滤了同样多次。
    如果用 it = filter(_not_divisible(n), it)的话,会把每次过滤的 n 记录下来,所以就会成功输出所有素数了。
    具体看上一层楼的例子。


    应该只有这个解释了。
    ballshapesdsd
        5
    ballshapesdsd  
       2017-09-22 17:08:56 +08:00
    如果用 it = filter(lambda x: x % n > 0, it)的话,比如说,next(it)要输出 5 的时候,会用 3 来过滤,如果 next(it)要输出 7 的话,就用 5 来过滤 2 次(当然和过滤 1 次一样),接下来输出 9,用 7 过滤,所以这样做等于把所有奇数都输出出来了。
    wang9571
        6
    wang9571  
       2017-09-22 17:17:57 +08:00
    其实就是 1 楼说的问题
    你改成 lambda n: lambda x: x % n > 0 试试
    ballshapesdsd
        7
    ballshapesdsd  
       2017-09-22 17:32:34 +08:00
    @wang9571
    什么鬼。。
    kkzxak47
        8
    kkzxak47  
       2017-09-22 17:32:45 +08:00 via Android
    lambda 的返回值和 def 一样是个函数
    khowarizmi
        9
    khowarizmi  
       2017-09-22 20:23:18 +08:00 via iPhone
    it 会形成嵌套的 generator,lambda 中 n 是引用(所以会变,都是同一个),而经过函数的 n 会被拷贝一份放闭包里。
    Technetiumer
        10
    Technetiumer  
       2017-09-22 20:55:34 +08:00 via Android
    @rwdy2008 回复里可以 Gist
    ManjusakaL
        11
    ManjusakaL  
       2017-09-22 22:20:06 +08:00
    @khowarizmi 正解
    Jeepeng
        12
    Jeepeng  
    OP
       2017-09-22 23:08:48 +08:00
    @rwdy2008
    filter 第一个参数是函数,_not_divisible(n) 是函数, lambda x: x % n > 0 也是函数,这个参数没问题
    Jeepeng
        13
    Jeepeng  
    OP
       2017-09-22 23:12:32 +08:00
    @wang9571
    如果要这样改的话,应该改成:(lambda n: lambda x: x % n > 0)(n)
    LeonHuayra
        14
    LeonHuayra  
       2017-09-22 23:25:52 +08:00
    @khowarizmi 赞同使用函数形成闭包的解析。直接使用 lambda 表达式是无法形成闭包的
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2843 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 07:03 · PVG 15:03 · LAX 23:03 · JFK 02:03
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.