Python面试题思考-3

Python的垃圾回收机制

  • 引用计数
    简单来说,为每个对象维护一个ob_ref字段,使其记录该对象当前被引用的次数,有了新的引用指向该对象时,引用计数+1,若有引用失效时,引用次数-1,待对象的引用次数为0时,该对象被回收。
    缺点主要有二:
    1、需要占用额外的内存空间存储该字段;
    2、若出现“循环引用”,则会造成内存泄漏(为解决该问题,引入”标记-清除“&”分代回收“);

  • 标记-清除
    这是一种基于追踪回收的的算法,主要分为两个阶段:

    1、将所有活动对象全部做好标记;
    2、将没有标记的对象作为”非活动对象“进行回收;

    对象通过引用链接在一起,构成一个有向图,对象为其中的节点,引用关系为其中的边,从根对象(全局变量、调用栈、寄存器)开始遍历该有向图,可达到的对象标记为活动对象,不可到达的对象标记为非活动对象。
    缺点:
    在每次清除对象前都需要扫描整个内存

  • 分代回收
    是一种以空间换时间的方式,在Python中将内存根据对象的存活时间划分为3个不同的集合(代),为年轻代(第0代)、中年代(第1代)、老年代(第2代),分别对应三个链表,它们的垃圾收集频率与对象的存活时间的增大而减小。新创建的对象都会分配在年轻代,年轻代链表的总数达到上限时,Python垃圾收集机制就会被触发,把那些可以被回收的对象回收掉,而那些不会回收的对象就会被移到中年代去,依此类推,老年代中的对象是存活时间最久的对象,甚至是存活于整个系统的生命周期内。同时,分代回收是建立在标记清除技术基础之上。分代回收同样作为Python的辅助垃圾收集技术处理那些容器对象。

Python中的垃圾回收机制

魔法方法

  • __call__:
    __call__函数的作用就是使得定义的类可以像函数形式一样被调用(可调用对象),具体请见下例:
    比如我定义了一个类A,其中定义了四个函数,__init__, hmh, cs, __call__。实现功能均不相同,然后将类A实例化为a,如果使用a(参数)的形式调用,那默认就是实现了__call__函数中的功能,如果我想实现hmhcs的功能,就还是要用a.hmh()a.cs()这样传统的调用形式。
   class A(object):
   def __init__(self):
       pass
   
   def __call__(self, *args, **kwargs):
       print(*args)
   
   def hmh(self):
       print("hmh")
   
   def cs(self):
       print("cs")
   
   a = A()
   a(12345)
   a.hmh()
>>>12345
>>>hmh
  • __new__:
    该方法需要接收一个类作为参数(此参数在实例化的时候由python解释器自动提供),从而产生一个实例,创建实例的,也就是说它起到的是构造类实例的作用。而__init__是在构造了实例后,对实例进行初始化的魔法方法。
  • __del__:
    起到析构的作用,用以销毁对象,但是一般情况下,python的内存机制可以很好的胜任销毁对象的工作,也可以手动使用__del__来进行这项工作。

元类

在python中一个重要的概念就是一切皆对象,也经常使用实例化的方法将定义的类变为一个个的实例,而元类就是构造类的方法,元类->类->实例。
什么是Python元类
两句话轻松掌握 python 最难知识点——元类

猴子补丁

猴子补丁(monkey patch),主要功能是动态的属性的替换,也就是在python代码运行时动态的改变方法、类的方法。但是补丁的存在可能会使得代码逻辑变得混乱。
详见:python面试题精讲——monkey patch(猴子补丁)

反射机制

有时我们需要访问对象中的某个变量、执行对象中的某个方法,但是我们可能不知道这个变量或者方法是否存在,所以需要一个机制可以让我们对未知的变量或方法进行了解或操作,这种机制就称之为反射,其中有几个方法:

  • hasattr:hasattr(object, name)
    判断对象中是否存在某变量或方法。
   class Hello(object):
       name = "hmh"
   
       def say_hello(self, sentence):
           print("Hello, %s" % self.name)

   hello = Hello()
   print(hasattr(hello, "name"))
   >>>
   True
  • getattr:getattr(object, name, [, default])
    获取对象中变量或方法,其中default是返回默认值,缺省如没有对应属性,会触发异常AttributeError
   class Hello(object):
       name = "hmh"
   
       def say_hello(self, sentence):
           print("Hello, %s" % self.name)

   hello = Hello()
   print(getattr(hello, "name"))
   >>>
   hmh
  • setattr:set(object, name, value)
    用于设置属性值,该属性不一定存在。
   class HMH(object):
       name = "hmh"
   
   
   hmh = HMH()
   setattr(hmh, "age", 23)
   
   print(hmh.age)
   >>>
   23

当然在很多场景下也是配合getattr使用。

   class HMH(object):
       name = "hmh"
   
   
   hmh = HMH()
   print(getattr(hmh, "name"))
   setattr(hmh, "name", "pluto")
   
   print(hmh.name)
   >>>
   hmh
   pluto 
   ```

* `delattr`:`delattr(object, name)`
  用于删除属性。
  
```python
   class HMH(object):
       name = "hmh"
       age = 23
   
   
   hmh = HMH()
   print(getattr(hmh, "name"))
   delattr(hmh, "name")
   
   print(hmh.name)
   >>>
   hmh
 File "/Users/houminghui/PycharmProjects/test_tensorflow/l_test.py", line 256, in <module>
   delattr(hmh, "name")
AttributeError: name
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值