首页   注册   登录
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python 学习手册
Python Cookbook
Python 基础教程
Python Sites
PyPI - Python Package Index
http://www.simple-is-better.com/
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
华为云
V2EX  ›  Python

求助,分开写输出是[12, 13, 14, 15];用 for 输出是[20, 21, 22, 23],请问为啥呢

  •  
  •   ropon · 12 天前 · 2126 次点击
    def add(a, b):
    return a + b

    def test():
    for r_i in range(4):
    yield r_i

    g = test()
    #0 1 2 3

    # g = (add(2, i) for i in g)
    # g = (add(10, i) for i in g)
    # print(list(g))
    #[12, 13, 14, 15]

    for n in [2, 10]:
    # 0 1 2 3
    # 2 1 2 3
    g = (add(n, i) for i in g)
    #第一次循环 n=2,i 第一次循环 0 相加结果 2 3 4 5
    #第二次循环 n=10,i 第一次循环 2 相加结果 12 13 14 15
    print(list(g))
    #为啥输出[20, 21, 22, 23]
    20 回复  |  直到 2018-10-09 23:13:48 +08:00
        1
    xyxc0673   12 天前
    打印 add 的参数 a 和 b,可以发现 a 在循环的方式中始终是 10,也就是 n 引用的始终是最后一次循环 n 的值,这和直接传值的方式是不一样的。
        2
    xyxc0673   12 天前   ♥ 1
    @xyxc0673 #1 如果用列表生成式就不会出现这种情况,因为生成器只有在被遍历时才会进行运算。
        3
    xyxc0673   12 天前
    @xyxc0673 #2 列表生成式则会一次性进行所有的运算
        4
    ropon   12 天前
    换成列表生产式 g = [add(n, i) for i in g],for 和单独传值结果一致[12, 13, 14, 15],不明白是怎么推算出[20, 21, 22, 23],for 第二次循环会覆盖上次循环的值吧。
        5
    ballshapesdsd   12 天前
    感觉是 python 语言的糟粕。。
        6
    ropon   12 天前
    如果遍历一次生成器表达式,那么 g 就没值了,生成器表达式 g = (add(n, i) for i in g) for i in g 不会遍历 g 么
        7
    xyxc0673   12 天前
    @ropon #6 g 在第一次遍历时没值了,但是你又赋值给 g 了。。。
        8
    ropon   12 天前
    @xyxc0673 逐级遍历吧
    比如一开始 g 是 0 1 2 3,第一次循环 的第一次遍历
    2 1 2 3
    2 3 2 3
    2 3 4 3
    2 3 4 5

    这样理解对么
        9
    goofool   12 天前
    n 一直是 10 哇,结果应该是 10+10+i
        10
    ropon   12 天前
    @goofool 10+10+i 是怎么来的呢
        11
    xyxc0673   12 天前
    @ropon #8 不懂你在讲哪个方面了。。。
    在循环的方式下,第一次循环时,g 的值为
    (
    add(2, 0),
    add(2, 1),
    add(2, 2),
    add(2, 3)
    )
    第二次循环时,g 的值为
    (
    add(10, add(10, 0)),
    add(10, add(10, 1)),
    add(10, add(10, 2)),
    add(10, add(10, 3))
    )
        12
    ropon   12 天前
    @xyxc0673 原来如此,明白了,感谢
        13
    goofool   12 天前
    @ropon 我记得叫 late binding 机制吧,两次计算的时候 n=10
        14
    goofool   12 天前 via Android
    @goofool 你把 2 改成 None 或者字符串,你就发现问题了
        15
    savebox   12 天前
    g = (add(n, i) for i in g) 改成 g = [add(n, i) for i in g] 就达到要求了
        16
    ropon   12 天前
    @xyxc0673 整理如下,看理解对吗?

    #总结:推导式有,列表推导式、字典推导式、集合推导式,没有元组推导式
    #生成器表达式:(结果 for 变量 in 可迭代对象 if 条件) 生成器表达式可直接获取其对象,对象可直接使用 for 循环,生成器具有惰性机制

    def add(a, b):
    return a + b

    def test():
    for r_i in range(4):
    yield r_i

    g = test()
    #0 1 2 3

    # g = (add(2, i) for i in g)

    #g 的值是
    # (
    # add(2, 0),
    # add(2, 1),
    # add(2, 2),
    # add(2, 3)
    # )

    # g = (add(10, i) for i in g)

    #g 的值是
    # (
    # add(10, add(2, 0)),
    # add(10, add(2, 1)),
    # add(10, add(2, 2)),
    # add(10, add(2, 3))
    # )
    #遍历生成器开始运算输出结果
    # print(list(g))
    #输出[12, 13, 14, 15]

    for n in [2, 10]:
    # g = [add(n, i) for i in g] #列表生成式会一次性进行所有的运算
    # 第一次循环 n=2,i 第一次循环 0 相加结果 2 3 4 5
    # 第二次循环 n=10,i 第一次循环 2 相加结果 12 13 14 15

    g = (add(n, i) for i in g) # 生成器表达式只有在被遍历时才会进行运算
    #第一次循环 n=2,i 从 0 1 2 3 循环,因生成器具有惰性机制,n 并没有取对应值,只是指向对应内存地址,g 的值是
    # (
    # add(n, 0),
    # add(n, 1),
    # add(n, 2),
    # add(n, 3)
    # )
    #第二次循环 n=10,i 从 add(2, 0) add(2, 1) add(2, 2) add(2, 3)循环,同理,g 的值是
    # (
    # add(n, add(n, 0)),
    # add(n, add(n, 1)),
    # add(n, add(n, 2)),
    # add(n, add(n, 3))
    # )
    #for 循环完,系统会释放 n,释放之前 n 先取值,g 的值是
    # (
    # add(10, add(10, 0)),
    # add(10, add(10, 1)),
    # add(10, add(10, 2)),
    # add(10, add(10, 3))
    # )
    #遍历生成器开始运算输出结果
    print(list(g))
    #输出[20, 21, 22, 23]
        17
    ropon   12 天前
    a = [1, 2]
    a[1] = a
    print(a[1])
    补门一个问题
    为啥结果是:
    [1, [...]]
        18
    ruoxin123   12 天前
    @ropon
    因为 a[1]是 a 自己啊
    所以会无限循环下去
    你会发现 a[1], a[1][1], a[1][1][1]... 都是[1, [...]]
        19
    xyxc0673   12 天前
    @ropon #16

    @goofool #13 说的准确一些,因为 lambda 表达式放在列表生成式也会出现这种现象,具体的讲解可以搜索关键词 late binding
        20
    ropon   12 天前
    @ruoxin123
    a[1]=a
    第一次 a=[1, [1, 2] ] 第二次 a=[1, [1, [1, 2] ] ] 第三次 a=[1, [1, [1, [1, 2] ] ] ]
    这样理解对吗
    关于   ·   FAQ   ·   API   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   734 人在线   最高记录 3762   ·  
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.1 · 21ms · UTC 18:25 · PVG 02:25 · LAX 11:25 · JFK 14:25
    ♥ Do have faith in what you're doing.
    沪ICP备16043287号-1