美文网首页
15-内存管理

15-内存管理

作者: 痞子_4ae7 | 来源:发表于2020-05-15 16:10 被阅读0次

元类

  • 类也是对象(属于元类的对象)

    #打印字符串(字符串是对象)
    print("HelloWorld")
    #打印类名,类同样为一个对象
    print(Person)
    
  • 使用动态创建类:

    • 语法:
    type(类名,由父类名称组成的元组(可以为空),包含属性的字典(名称和值))
    
    案例1:使用type创建类
    Myclass = type("MyClass3",(),{})
    m1 = Myclass()
    print(type(m1))
    
    案例2:使用type创建带有属性(方法)的类
    def show(self):
        print("---num---%d"%self.num)
    #  使用元类(type)创建类
    Test = type("Test",(),{"show":show})
    t = Test()
    t.num = 100
    t.show()
    
    案例3:使用type动态创建一个继承指定类的类
    class Animal():
        def __init__(self,color="Yellow"):
            self.color = color
        def eat(self):
            print("吃死你")
    Dog = type("Dog",(Animal,),{})
    dog = Dog()
    dog.eat()
    print(dog.color)
    

类装饰器

class Test(object):
    def __init__(self,func):
        print("--初始化--")
        print("func name is %s"%func.__name__)
        self.__func = func
    # 重写该方法后,对象可以直接进行调用
    def __call__(self):
        print("--装饰器中的功能--")
        self.__func()
# @Test 等价于  test = Test(test) 装饰器特性
@Test
def test():
    print('--test 函数---')
# 本身test指向函数test,但是装饰器将test指向了对象。
#  对象本身不可以被调用,但是重写__call__方法之后则会被调用
test()
执行结果:
--初始化--
func name is test
--装饰器中的功能--
--test 函数---

对象池

什么叫做垃圾回收?
生活案例

  • 小整数池

    • 系统默认创建好的,等着你使用
    • 概述
      整数在程序中的使用非常广泛,Python为了优化速度,使用了小整数对象池,
      避免为整数频繁申请和销毁内存空间。Python 对小整数的定义是 [-5, 256]
      这些整数对象是提前建立好的,不会被垃圾回收。在一个 Python 的程序中,
      无论这个整数处于LEGB(局部变量,闭包,全局,内建模块)中的哪个位置,
      所有位于这个范围内的整数使用的都是同一个对象。
    案例:(必须使用终端验证,pycharm每次都是所有代码都加载到内存中,
    被看成是一个整体)
    代码验证小整数
    a = 100
    print(id(a))
    del a
    b = 100
    print(id(b))
    发现删除a后,b的地址依旧是删除之前的那个地址(是否删除,小整数都常驻内存)
    
  • 大整数池
    默认创建出来,池内为空的,创建一个就会往池中存储一个

    案例验证
    代码验证大整数
    
  • intern机制

    • 每个单词(字符串),不夹杂空格或者其他符号,默认开启intern机制,共享内存,靠引用计数决定是否销毁
    案例验证:
    a = 'HelloWorld'
    b = 'HelloWorld'
    print(a is b)
    
    a = 'Hello World'
    b = 'Hello World' 
    print(a is b)
    

垃圾收集

概述:
现在的高级语言如java,c#等,都采用了垃圾收集机制,
而不再是c,c++里用户自己管理维护内存的方式。自己管理内存极其自由,
可以任意申请内存,但如同一把双刃剑,为大量内存泄露,悬空指针等bug埋下隐患。
python里也同java一样采用了垃圾收集机制,不过不一样的是:
python采用的是引用计数机制为主,标记-清除和分代收集两种机制为辅的策略
  • 引用计数
python里每一个东西都是对象,它们的核心就是一个结构体:PyObject
 typedef struct_object {
        int ob_refcnt;
        struct_typeobject *ob_type;
    } PyObject;
PyObject是每个对象必有的内容,其中ob_refcnt就是做为引用计数。
当一个对象有新的引用时,它   的ob_refcnt就会增加,当引用它的
对象被删除,它的ob_refcnt就会减少
#define Py_INCREF(op)   ((op)->ob_refcnt++) //增加计数
    #define Py_DECREF(op) \ //减少计数
        if (--(op)->ob_refcnt != 0) \
            ; \
     else \
            __Py_Dealloc((PyObject *)(op))
当引用计数为0时,该对象生命就结束了。
  • 引用计数机制的优点:

    • 1.简单
    • 2.实时性:一旦没有引用,内存就直接释放了。不用像其他机制等到特定时机。
      实时性还带来一个好处:处理回收内存的时间分摊到了平时。
  • 引用计数机制的缺点:

    • 1.维护引用计数消耗资源
    • 2.循环引用的问题无法解决(DOS窗口,查看内存tasklist,或者内存表,任务管理器)
    案例:
    import gc
    class AAA(object):
        def __init__(self):
            print ("object: born at:%s"%hex(id(self)))
        def __new__(cls, *args, **kwargs):
            print ("new")
            return super(AAA, cls).__new__(cls)
        def __del__(self):
            print ("bye bye")
    def start():
        while True:
            a = AAA()
            b = AAA()
            a.v = b
            b.v = a
    #无法删除
            del a
            del b
    gc.disable()
    start()
    
  • 隔代回收

    分代回收是用来解决交叉引用(循环引用)
    ,并增加数据回收的效率. 原理:通过对象存在
    的时间不同,采用不同的算法来 回收垃圾. 形象的比喻, 
    三个链表,零代链表上的对象(新创建的对
    象都加入到零代链表),引用数都是一,每
    增加一个指针,引用加一,随后python会检
    测列表中的互相引用的对象,根据规则减
    掉其引用计数. 
    GC算法对链表一的引用减一,引用为0的,
    清除,不为0的到链表二,链表二也执行GC
    算法,链表三一样. 
    存在时间越长的数据,越是有用的数据
    
    • 隔代回收触发时间?(GC阈yu值)
    随着你的程序运行,Python解释器保持对新创建的对象,
    以及因为引用计数为零而被释放掉的对象的追踪。从理论上说,
    这两个值应该保持一致,因为程序新建的每个对象都应该最终被释放掉。
    当然,事实并非如此。因为循环引用的原因,从而被分配对象的计数值
    与被释放对象的计数值之间的差异在逐渐增长。一旦这个差异累计超过某个阈值,
    则Python的收集机制就启动了,并且触发上边所说到的零代算法,
    释放“浮动的垃圾”,并且将剩下的对象移动到一代列表。
    随着时间的推移,程序所使用的对象逐渐从零代列表移动到一代列表。
    而Python对于一代列表中对象的处理遵循同样的方法,一旦被分配计数值
    与被释放计数值累计到达一定阈值,Python会将剩下的活跃对象移动到二代列表。
    通过这种方法,你的代码所长期使用的对象,那些你的代码持续访问的活跃对象,
    会从零代链表转移到一代再转移到二代。通过不同的阈值设置,Python可以在
    不同的时间间隔处理这些对象。Python处理零代最为频繁,其次是一代然后才是二代。
    
  • 查看引用计数

    • gc模块的使用

      常用函数:
      1、gc.get_count()
      获取当前自动执行垃圾回收的计数器,返回一个长度为3的列表
      2、gc.get_threshold()
      获取gc模块中自动执行垃圾回收的频率
      3、gc.set_threshold(threshold0[,threshold1,threshold2])
      设置自动执行垃圾回收的频率
      4、gc.disable()
      python3默认开启gc机制,可以使用该方法手动关闭gc机制
      5、gc.collect()
      手动调用垃圾回收机制回收垃圾
      
    • 增加引用计数的条件

      • a.创建对象

        stu = Student()
        
      • b.将对象加入列表

        list1.append(stu)
        
      • c.对象被引用

        stu2 = stu
        
      • d.将对象作为参数,传入某个函数

        func(stu)
        
    • 减少对象引用计数的情况

      • a.对象被显示销毁

        del stu
        
      • b.对象名指向新的对象

        stu = Student()
        
      • c.从容器中移除,或者显示销毁列表

        list1.remove(stu)
        list1.pop(stu)
        
      • d.局部变量对象,作为函数参数,

        函数结束时,引用计数-1
        
      • 获取某个对象的引用计数

      import sys
      obj = 'Helloworld'
      sys.getrefcount(obj)
      list1 = []
      list.append(obj)
      sys.getrefcount(obj)
      

内建属性

  • 常用专有属性
    • 常用内置类属性

      __dict__:
      类的属性(包含一个字典,由类的数据属性组成)
      __doc__:
      类的文档字符串
      __name__:
       类名
      __module__:
      类定义所在的模块
      __bases__:
      类的所有父类构成元素(包含了以个由所有父类组成的元组)
      
    • 属性拦截器getattribute

      class Test(object):
          def __init__(self,var1):
              self.var1 = var1
          #  该方法在获取对象属性的时候会被调用,
          def __getattribute__(self,obj):
              if obj == 'var2':
                  print("属性var1拦截成功")
                  return '我是拦截后替换的数据'
              else:
                  # 如果拦截不成功,可以调用父类的方法,这时候obj的值就是init中的值
                  return object.__getattribute__(self,obj)
                  # 如果在__getattribute__方法中,
                  # 使用使用self访问属性,或者方法,都会导致程序崩溃
                  # return self.var1
          def show(self):
              print("我是show方法")
      
      s = Test("python")
      # 成员变量 var1会被以字符串的形式('var1')传递给__getattribute__方法的obj
      print(s.var1)
      # 方法的访问也可以通过属性拦截器进行拦截
      s.show()
      

内建函数

  • 什么叫内建函数:

    启动python解释器后,默认加载的函数称为内建函数
    
  • 如何查看内建函数

    两种方式:
    a. dir(__builtins__)
    b.  import builtins
    dir(builtins)
    
  • 常用内建函数:

    • range()

      python range() 函数可创建一个整数列表,一般用在 for 循环中。
      语法:
      range(start, stop[, step])
      参数说明:
      start: 计数从 start 开始。默认是从 0 开始。例如range(5)等价于range(0, 5);
      stop: 计数到 stop 结束,但不包括 stop。例如:range(0, 5) 是[0, 1, 2, 3, 4]没有5
      step:步长,默认为1。例如:range(0, 5) 等价于 range(0, 5, 1)
      返回:range
      案例:
      代码验证
      
    • map()

      map() 会根据提供的函数对指定序列做映射。
      第一个参数 function 以参数序列中的每一个元素调用 function 函数,
      返回包含每次 function 函数返回值的新列表。
      语法:
      map(function, iterable, ...)
      参数说明:
      function -- 函数
      iterable -- 一个或多个序列
      返回:
      Python 2.x 返回列表。
      Python 3.x 返回迭代器。
      案例:
      from collections import Iterable
      from collections import Iterator
      def func(x,y):
          return x*y
      # 使用匿名函数
      v = map(lambda x:x*2,[1,2,3])
      print(type(v))
      print(isinstance(v,Iterable))
      print(isinstance(v,Iterator))
      for x in v:
          print(x)
      # 两个参数
      v1 = map(func,[1,2,3],[4,5,6])
      v2 = list(v1)
      print(type(v2))
      
    • filter()

      filter() 函数用于过滤序列,过滤掉不符合条件的元素,返回由符合条件元素组成的新列表。
      该接收两个参数,第一个为函数,第二个为序列,
      序列的每个元素作为参数传递给函数进行判断,然后返回 True 或 False,
      最后将返回 True 的元素放到新列表中。
      语法:
      filter(function, iterable)
      参数说明:
      function -- 判断函数。
      iterable -- 可迭代对象。
      返回:
      返回迭代器。
      案例:
      def func2(x):
          return  x % 2 == 0
      # 找出1-100中的偶数
      list2 =  filter(func2,[x for x in range(1,100)])
      print(isinstance(list2,Iterator))
      for x in list2:
          print(x)
      
    • reduce()

      3.x后,需要先from functools import reduce
      reduce() 函数会对参数序列中元素进行累积。
      函数将一个数据集合(链表,元组等)中的所有数据进行下列操作:
      用传给reduce中的函数 function(有两个参数)先对集合中的第 1、2 个元素进行操作,
      得到的结果再与第三个数据用 function 函数运算,最后得到一个结果。
      语法:
      reduce(function, iterable[, initializer])
      参数说明:
      function -- 函数,有两个参数
      iterable -- 可迭代对象
      initializer -- 可选,初始参数
      返回:
      返回函数计算结果
      案例:求列表所有值的和 
      from functools import reduce
      v = reduce(lambda x,y:x+y,[1,2,3,4],5)
      print(v)
      v = reduce(lambda x,y:x+y,['1','2','3','4'],'5')
      print(v)
      案例: 求列表中数字所能表示的整型数
      --------------------
      def func_4(x,y):
          return x * 10 + y
      list3 = [1,2,3,4]
      value = reduce(func_4,list3)
      print(value)
      
    • sorted()

      sorted() 函数对所有可迭代的对象进行排序操作。
      sort 与 sorted 区别:
      sort 是应用在 list 上的方法,sorted 可以对所有可迭代的对象进行排序操作。
      list 的 sort 方法返回的是对已经存在的列表进行操作,
      而内建函数 sorted 方法返回的是一个新的 list,而不是在原来的基础上进行的操作
      语法:
      sorted(iterable[, key[, reverse]])
      参数说明:
      iterable -- 可迭代对象。
      key -- 主要是用来进行比较的元素,只有一个参数,具体的函数的参数就是取自于可迭代对象中,指定可迭代对象中的一个元素来进行排序。
      reverse -- 排序规则,reverse = True 降序 , reverse = False 升序(默认)
      返回:
      返回重新排序的列表。
      案例:
      class Student():
          def __init__(self,name,age):
              self.name = name
              self.age = age
          def __str__(self):
              return self.name+str(self.age)
      students = [('john', 'A', 15), ('jane', 'B', 12), ('dave', 'B', 10)]
      # 根据
      students = sorted(students,key=lambda s:s[1])
      print(students)
      
      students = [Student('jj',12),Student('dd',19),Student('xx',32)]
      # 自定义对象的排序
      students1 = sorted(students,key=lambda x:x.name)
      for s in students1:
          print(s)
      

集合

  • 概念

    类似于列表的一种容器,可以存储多个数据,无序,唯一
    
  • 用法:

    • 添加、删除元素

      add()
      remove()
      
    • 数学运算

      a = {1,2,3}
      b = {3,4,5}
      &:
      a & b
      |:
      a | b
      -:
      a - b
      ^:
      a ^ b
      

常用模块

  • 常见模块列表

    builtins                内建函数默认加载
    os                  操作系统接口
    sys                 python自身运行环境
    functools               常用的工具
    json                    编解码json对象
    logging             记录日志
    time                    时间
    datetime                日期和时间
    calendar                日历
    multiprocessing     进程
    threading               线程
    copy                    复制
    hashlib             加密
    re                  正则
    socket              标准BSD  socket API
    
  • hashlib的加密验证(账户密码验证)

    from  hashlib import *
    m = md5()
    account = '13388888888'
    pw = '123456'
    # 使用md5方式加密
    m.update(account.encode())
    # 打印加密后的结果
    print(m.hexdigest())
    
  • 常用扩展库(第三方库)

    requests 使用的是 urllib3, 继承了urllib2的所有特性
    urllib 基于http的高层库
    scrapy 爬虫
    beautifulsoup4 HTML/XML的解析器
    celery 分布式任务调度模块
    redis 缓存
    Pillow(PIL) 图像处理
    xlsxwriter 仅写excle功能,支持xlsx
    xlwt 仅写excle功能,支持xls ,2013或更早版office
    xlrd 仅读excle功能
    elasticsearch 全文搜索引擎
    pymysql 数据库连接库
    mongoengine/pymongo mongodbpython接口
    matplotlib 画图
    numpy/scipy 科学计算
    django/tornado/flask web框架
    xmltodict xml 转 dict
    SimpleHTTPServer 简单地HTTP Server,不使用Web框架
    gevent 基于协程的Python网络库
    fabric 系统管理
    pandas 数据处理库
    scikit-learn 机器学习库
    python本地服务器开启
    python -m http.server 8888
    

相关文章

  • 15-内存管理

    元类 类也是对象(属于元类的对象)#打印字符串(字符串是对象)print("HelloWorld")#打印类名,类...

  • iOS内存管理详解

    目录 block内存管理 autorelease内存管理 weak对象内存管理 NSString内存管理 new、...

  • 第10章 内存管理和文件操作

    1 内存管理 1.1 内存管理基础 标准内存管理函数堆管理函数虚拟内存管理函数内存映射文件函数 GlobalMem...

  • 操作系统之内存管理

    内存管理 包括内存管理和虚拟内存管理 内存管理包括内存管理概念、交换与覆盖、连续分配管理方式和非连续分配管理方式(...

  • JavaScript —— 内存管理及垃圾回收

    目录 JavaScript内存管理内存为什么需要管理?内存管理概念JavaScript中的内存管理JavaScri...

  • OC - OC的内存管理机制

    导读 一、为什么要进行内存管理 二、内存管理机制 三、内存管理原则 四、MRC手动内存管理 五、ARC自动内存管理...

  • 3. 内存管理

    内存管理 内存管理包含: 物理内存管理; 虚拟内存管理; 两者的映射 除了内存管理模块, 其他都使用虚拟地址(包括...

  • Go语言——内存管理

    Go语言——内存管理 参考: 图解 TCMalloc Golang 内存管理 Go 内存管理 问题 内存碎片:避免...

  • jvm 基础第一节: jvm数据区

    程序内存管理分为手动内存管理和自动内存管理, 而java属于自动内存管理,因此jvm的职能之一就是程序内存管理 j...

  • 内存管理

    内存管理的重要性。 不进行内存管理和错误的内存管理会造成以下问题。 内存泄露 悬挂指针 OC内存模型 内存管理是通...

网友评论

      本文标题:15-内存管理

      本文链接:https://www.haomeiwen.com/subject/vbqtohtx.html