吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 1927|回复: 10
收起左侧

[讨论] python关于lambda、引用传递等易犯的错误

[复制链接]
井右寺 发表于 2019-8-24 20:10
本帖最后由 井右寺 于 2019-8-24 20:18 编辑

这个坑,已经趟过无数次了....
然而下次遇到了,还是习惯错误的写法,记录一下,也给大家提个醒——
测试例子如下,猜一下最后输出会是什么,和最后结果会不会有差异
[Python] 纯文本查看 复制代码
import time
import threading

def test(i,count, _type):
        time.sleep(3)
        if lock.acquire():
                if type(count) == int:
                        count += 1
                else:
                        count[0] += 1 
                lock.release()

        print(_type, ":", i, count)

if __name__ == '__main__':
        threads = []
        lock = threading.Lock()
        # 情况一
        cnt = 0
        for i in range(3):
                threads.append(threading.Thread(target=test, args=(i,cnt, "type 1")))

        # 情况二
        cnt2 = [0]

        for j in range(3,6):
                threads.append(threading.Thread(target=lambda: test(j, cnt2, "type 2")))

        for t in threads:
                t.daemon = True
                t.start()

        for t in threads:
                t.join()

        # 这是几
        print(cnt)
        # 这又是几
        print(cnt2)

        input("end!")


——————————————————————————分割线————————————————————————————————
打印结果应该如下(线程完成时间可能有差异,这个不影响)
[HTML] 纯文本查看 复制代码
type 1:  0  1
type 1:  1 1
type 1:  2  1
type 2:  5  [1]
type 2:  5 [2]
type 2:  5 [3]
0
[3]

和你想的有没有差距呢?
涉及到的原因:
1、lambda返回的是一个匿名函数,而不是函数执行。在实际start执行的时候才进行的lambda表达式的执行,这个时候 j已经成为了5。
2、值传递和引用传递的问题,简单类型会进行值传递,复杂类型才会进行引用传递。int为简单类型,值被传递进去,所以函数外的变量未被修改,而array为复杂类型,把引用传递进去了,函数会影响参数变量。

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

 楼主| 井右寺 发表于 2019-8-24 20:13
我都不知道为什么,我线程操作,习惯性使用lambda
DocL 发表于 2019-8-24 20:26
weidian 发表于 2019-8-24 20:28
fhxylang 发表于 2019-8-24 20:43
怎么都是Python,有没有java?
歆堇 发表于 2019-8-24 20:51
学Python难吗?
 楼主| 井右寺 发表于 2019-8-24 21:03
fhxylang 发表于 2019-8-24 20:43
怎么都是Python,有没有java?

java的lambda没用过呢
蹭热度啊....
 楼主| 井右寺 发表于 2019-8-24 21:04

简单
但是最好有一定编程基础
我反正不太建议,以python做入门语言(因为太简单、灵活了,会养成坏习惯的)
prty 发表于 2019-8-24 21:06
用多线程干什么。。。 新手吧 楼主 。。。  用协程吧  这种小计算情况 线程切换占大头
 楼主| 井右寺 发表于 2019-8-24 21:08
DocL 发表于 2019-8-24 20:26
为什么3个线程的输出j都是五呢?

lambda是匿名函数,thread声明的时候只为这个匿名函数准备了执行环境
但是因为lambda并没有执行,所以他内部调用的函数,test的环境并不是在thread声明那里完成的
而是在start那里才开始 test函数的准备执行,这个时候上下文环境中的J已经为5了
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-30 11:52

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表