zoukankan      html  css  js  c++  java
  • ------------------------------匿名函数---玩法==补充:垃圾回收机制

    Lambda函数可以具有任意数量的参数,但只能有一个表达式。该表达式将被求值并返回

    f = lambda x, y: x ** y  # 返回x的y次方
    f1 = lambda x: x + 1     # 返回x+

    我们通常使用Lambda函数作为高阶函数的参数,该函数以其他函数作为参数。匿名函数与内置函数(如 filter(), map() 等)一起使用

    # filter(function or None, iterable) --> filter object
    # 过滤器,返回一个迭代器保留那些func(item)之后为True的项,
    # 如果function为none,返回为True的项
    # 例如:filter(lambda n:n>5,range(10))
    # 派生:map(lambda n:n*2,range(10))
    # 派生:[abs(i) : for i in range(10)]
    # 派生:functools.reduce(lambda x,y:x*y,range(10))
    filter()
    # map(func, *iterables) --> map object
    # 制作一个迭代器,从每个可迭代对象获取参数用来计算函数。
    # 当短迭代耗尽的时候停止
    # 把一个或多个迭代器当成参数喂给函数,返回一个函数运行后的迭代器。
    map()  


    import functools
    r = functools.reduce(lambda x, y: x * y, range(1, 5)) # 1234
    # 用传给 reduce 中的函数 function(有两个参数)先对集合中的第 1、2 个元素进行操作,
    # 得到的结果再与第三个数据用 function 函数运算,最后得到一个结果
    print(r) #24



    内存管理


    综上所述,

    float对象在创建对象时会把为其开辟内存并初始化引用计数器为1,然后将其加入到名为 refchain 的双向链表中;

    float对象在增加引用时,会执行 Py_INCREF在内部会让引用计数器+1;

    最后执行销毁float对象时,会先判断float内部free_list中缓存的个数,如果已达到300个,则直接在内存中销毁,

    否则不会真正销毁而是加入free_list单链表中,以后后续对象使用,销毁动作的最后再在refchain中移除即可。 


    垃圾回收机制


    引用计数变为0导致垃圾回收机制的例子:

    class DictA(dict):
        def __del__(self):
            print("DictA被回收")
    
    
    class DictB(dict):
        def __del__(self):
            print("DictB被回收")
    
    
    a = DictA()
    b = DictB()
    
    a = 1
    b = 1
    # a=1;b=1导致引用计数变为0,立即触发垃圾回收机制,a,b会在“ok”之前被回收
    print("ok")
    
    # 输出结果:
    """
    DictA被回收
    DictB被回收
    ok
    """

    当对象的引用计数器为0时,就会被销毁并释放内存。而实际上他不是这么的简单粗暴。

    因为反复的创建和销毁会使程序的执行效率变低。Python中引入了“缓存机制”。
    例如:引用计数器为0时,不会真正销毁对象,而是将他放到一个名为 free_list 的链表中,之后会再创建对象时不会在重新开辟内存,而是在free_list中将之前的对象来并重置内部的值来使用

    float类型、int类型、str类型、list类型、tuple类型、dict类型分别有自己的链表存放垃圾对象。

    循环引用导致不能立即执行垃圾回收机制的例子

    class DictA(dict):
        def __del__(self):
            print("DictA被回收")
    
    
    class DictB(dict):
        def __del__(self):
            print("DictB被回收")
    
    
    a = DictA()
    b = DictB()
    
    a['xxx'] = b
    b['yyy'] = a
    
    a = 1
    b = 1
    # a=1;b=1不能使引用计数变为0,因为循环引用了,a,b会在打印“ok”之后被回收
    print("ok")
    
    # 输出结果:
    """
    ok
    DictA被回收
    DictB被回收
    """

    引用计数为主,标记清除和分代回收为辅

    python内部维护一个 refchain的“环状双向链表”, 创建的所有对象放在该链表中。

    对象内部有该对象的引用计数,当引用计数变为0,触发python的垃圾回收,将其放入缓存

    这样导致一个问题,循环引用永远不会被回收。为了解决这个问题,python引入三个“环状双向链表”

    0代,1代,2代。 创建对象时把可能发生循环引用的可变对象放入0代。当0代数量达到700时,

    python对其进行标记清除,引用计数-1,减1为0的进行回收。不为0的放入1代。

    依次类推。0代回收10次触发1代回收,1代回收10次触发2代回收。

    https://www.bilibili.com/video/BV1ok4y1B7eE?p=1

  • 相关阅读:
    Linux学习-网络管理
    Linux学习-文件权限
    Linux学习-用户管理常用命令
    python操作数据库(MySQL、redis、MD5加密函数)
    Jenkins待过的坑
    Robot framework+Jenkins
    jenkins + maven + SVN自动化集成部署
    接口测试学习笔记二
    接口测试学习笔记一
    【数据结构】为什么要使用一致性哈希算法?
  • 原文地址:https://www.cnblogs.com/staff/p/9272003.html
Copyright © 2011-2022 走看看