【Python面向对象03】底层与方法(详解python对象的生命周期)

底层与方法


1. 与函数的区别

调用方式不同

2. 方法的划分

  • 实例方法:第一个参数是实例
  • 类方法:第一个参数是类
  • 静态方法:第一个参数没有要求
  • 注意:
    1. 区分依据:观察第一个参数的默认类型
    2. 所有类型的方法都存储在类当中
    3. 不同方法调用方式不同,保证不同类型的方法第一个参数收 到的数据是其期望的类型
  • 使用:
    1. 语法
    2. 不同类型的方法规则以及调用
    3. 根据不同的问题,自主决定,适合设计什么样的方法解决问题

3. 实例方法

   #定义
   class ClassName:
      def funcname(self):
         pass

   #实例化并调用
   c = ClassName()
   c.funcname()
  • 调用:
    1. 标准调用:使用实例调用实例方法,解释器自动把调用对象本身传递过去;如果实例方法没有接受到任何参数,就会报错

4. 类方法

   #定义
   class ClassName:
      #装饰器
      @classmethod
      def func(cls):
         print("this is a classmethod",cls)
   
   #类调用
   ClassName.func()
   c = ClassName()
   #会找到实例的类,用类调用,实例会被忽略
   c.func()

   class A:
      pass
   #使用延伸类调用类方法的话,会把延伸类本身作为第一个参数传递给类方法
   A.func()
  • 注意:
    • 装饰器的作用:在保证原本函数不改变的前提下,直接给这个函数增加一些功能

5. 静态方法

   class Person:
      #装饰器
      @staticmethod
      def jingtai():
         pass
  • 注意:
    • 既可以通过实例调用也可以用类调用

6. 不同类型的方法访问不同类型的属性规律

  • 实例可以访问类的属性
  • 类不能访问实例的属性
  • 实例的属性可以在类外定义后,调用实例方法也依然能访问到该属性

7.Python对象的生命周期及方法

  1. 生命周期
  • 一个对象从诞生到消亡的过程
  • 当一个对象被创建,会在内存中分配相应的内存空间进行存储
  • 当这个对象不再使用,为了节约内存,就会把对象释放
  • 监听对象的生命周期
    • __new__方法:新建一个对象时,给对象分配内存的方法,拦截调用,即可修改对象创建过程
    • __init__方法:对一个对象进行初始化
    • __del__方法:当一个对象被释放时,自动调用

一个代码案例

# Person, 打印一下, 当前这个时刻, 由Person类, 产生的实例, 由多少个
# 创建了一个实例, 计数 + 1, 如果, 删除了一个实例, 计数 - 1

class Person:

   #类的私有属性
    __personCount = 0

    def __init__(self):
        print("计数 + 1")
        #类名调用
        Person.__personCount += 1

    def __del__(self):
        print("计数 - 1")
        #实例的类的调用
        self.__class__.__personCount -= 1

    @classmethod
    def log(cls):
         #类对象调用
        print("当前的人的个数是%d个" % cls.__personCount)

p = Person()      #输出:计数+1 
p2 = Person()     #输出: 计数+1
Person.log()      #输出:当前的人的个数是2个
del p             #输出:计数-1
del p2            #输出:计数-1
Person.log()      #输出:当前的人的个数是0个
  1. 内存管理机制(存储方面)
  • python中万物皆对象,所有对象,都会在内存中开辟一块空间进行存储
  • 会根据不同类型和内容,开辟不同的空间大小进行存储,返回该空间地址给外界接收(“引用”)
  • 可以同过id()获取内存地址;或者hex()查看对应的16进制地址
  • 对于整数和短小字符,python会进行缓存,不会创建多个相同的对象【此处结合python的可变不可变数据类型进行学习,可以参考我另一笔记
  • 容器对象,存储的其他对象,仅仅是其他对象的引用,而非其他对象本身
  1. 内存管理机制(垃圾回收方面)

python的 内存管理机制 = 引用计数器机制 +垃圾回收机制

  • 引用计数器:一个对象,会记录自身被引用的个数
  • 查看引用计数
import sys
#注意会比实际大1,但结束后会自动减1的
sys.getrefcount(对象)    
  • 引用计数器 + 1 场景:
    • 被创建:p1 = Person()
    • 被引用:p2 = p1
    • 作为参数传入一个函数
    • 作为一个元素存储在容器中:l = [p1]
  • 引用计数器 - 1 场景:
    • 被显示销毁: del p1
    • 别名被赋予新的对象: p1 = 123
    • 一个对象离开它的作用域:函数执行完毕时;
    • 对象所在容器被销毁,或从容器中删除对象

  • 垃圾回收:从经历过“引用计数器机制”仍未被释放的对象中,找到“循环引用”,干掉相关对象。【即,主要解决循环引用问题】

  • “循环引用”查找【较难,了解即可】:

    • 收集所有的容器对象[可以引用其他对象的对象,如列表、元组、字典、自定义对象等]
    • 对每个容器对象,通过变量gc_refs来记录当前对应的引用计数;
    • 对每个容器对象,找到它引用的容器对象,并将这个容器对象的引用计数-1
    • 经过上述步骤后,若一个容器对象的引用计数为0,就表示被回收了,肯定是循环引用致使其存活到现在
  • 分代回收【提升循环引用回收的性能】

    • 默认一个对象被创建出来后,属于0代
    • 如果经过这一代的“垃圾回收”后,依然存活,则划分到下一代
    • 其周期顺序为:
      • 0代“垃圾回收”一定次数,会触发0代和1代回收
      • 1代“垃圾回收”一定次数,会触发0代、1代、二代回收
    • 查看和设置相关参数
    import gc
    print(gc.get_threshold)
    #参数详解
    #700:新增数-消亡数 = 700触发检测
    #10: 0代检测十次触发0&1代检测
    #5: 1代检测5次触发0&1&2的检测
    gc.set_threshold(700,10,5)
    
  • 注意:垃圾回收器中,新增的对象个数-消亡的对象个数,达到一定的阈值时,才会触发垃圾检测

  • 垃圾回收时机

    • 自动回收:开启垃圾回收机制且打到了垃圾回收阈值
    import gc
    gc.enable()     #开启垃圾回收机制(默认开启)
    gc.disable()    #关闭垃圾回收机制
    gc.isenbaled()  #判断是否开启
    
    • 手动回收:
      • 利用弱引用weakref.ref(对象);或者自己将引用指向None
      • 多个弱引用可以使用
      weakref.WeakValueDictionary(字典对象)
      
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值