Django信号机制工作原理
在上一节《Django信号机制执行过程及其应用》一节,我们详解的介绍了 Django 信号机制的执行过程及其应用。通过上一节知识的学习,其实我们可以认识到信号的工作原理其实就是 Signal 对象的实现过程,在不同的阶段调用了 Signal 相应的方法,但是有些地方你可能还是会感到迷茫,比如什么是观察者模式?什么是 Python 语言的弱引用等,在本节我们将从 Python 语言的相关特性出发,介绍 Django 信号机制的工作原理。
观察者模式的两个重要角色即目标和观察者,为了形象的理解,我们把目标定义为杂志,把观察者定义为订阅了杂志的用户,当目标状态发生改变的时候,所有的观察者都会收到通知,并做出相应的动作。比如在微博或者论坛中,你发布了一个话题,那么关注你的粉丝就会收到一个通知,粉丝收到通知后可以相应的做出回馈。这也是观察者模式的适应场景。
从对观察者设计模式的说明与理解,我们可以得知 Django 信号机制就是观察者模式的实现。这种模式的优点非常明显,它在目标与观察者之间建立了轻度的关联关系,对于它们各自的扩展就会非常容易。在运行时,观察者可以动态地添加或删除(取关操作),对目标(话题发布者)不会有任何影响,反过来也是一样,所以它们是抽象耦合的。
Django 信号机制涉及了诸多方面的知识,本节我们只是讲了你可能没有涉猎过的知识点,比如,Django 信号机制还应用了 Python 线程的同步机制,也就是使用锁即 Lock 来避免多线程程序中对共享资源的竞争导致的错误。在这里就不进行介绍了,有兴趣的同学可以自己探索。
1. 观察者设计模式简述
1)观察者设计模式理解
观察者模式它定义了对象之间一对多的依赖关系,当一对象的状态发生改变的时候,所有依赖于它的对象都获取到通知并发生相应的改变。观察者模式还有一个别名叫做发布订阅模式,这个名字就非常的形象的说明了这种设计模式的理念,当订阅者订阅了某系列杂志,当杂志有了新的状态即发布者,比如更新了,那么此时就会给所有的订阅者发送一条消息,那么所有的订阅者就会收到此消息做出购买或不购买的选择。观察者模式的两个重要角色即目标和观察者,为了形象的理解,我们把目标定义为杂志,把观察者定义为订阅了杂志的用户,当目标状态发生改变的时候,所有的观察者都会收到通知,并做出相应的动作。比如在微博或者论坛中,你发布了一个话题,那么关注你的粉丝就会收到一个通知,粉丝收到通知后可以相应的做出回馈。这也是观察者模式的适应场景。
从对观察者设计模式的说明与理解,我们可以得知 Django 信号机制就是观察者模式的实现。这种模式的优点非常明显,它在目标与观察者之间建立了轻度的关联关系,对于它们各自的扩展就会非常容易。在运行时,观察者可以动态地添加或删除(取关操作),对目标(话题发布者)不会有任何影响,反过来也是一样,所以它们是抽象耦合的。
2. Python语言特性弱引用
学习过 Python 语言的小伙伴知道,Python 的垃圾回收由引用计数、标记清理和分代回收等方式构成。其中大部分对象的生命周期由对象的引用计数来管理。在 Python 语言中一切皆对象(还是 Python 好从不缺对象),每一个对象都会维护一个叫做 obrefcnt 的属性,也就是引用计数,当一个对象有了新的引用时,obrefcnt 就会加 1 ;当对象的引用被删除时就会就会减 1;当其为 0 的时候表示当前对象没有被使用,我们可以使用如下方式查看某个对象的引用计数值:import sys sys.getrefcount()#接受一个参数对象但是引用计数有一个明显的缺点就是无法解决循环引用的问题即 a 引用 b, b 引用 a,导致其引用计数永远不为 0,这样就会导致内存无法释放也浪费了系统内存,从而造成内存泄露的问题。为了避免这个问题 Python 提供了 weakref 即弱引用。它的效果是:当对一个对象创建了弱引用时,对象的引用计数不会增加。示例如下所示:
In [1]: import sys,weakref In [2]: class A: ...: def hello(self): ...: return "新宝库" ...: In [3]: a=A() In [4]: sys.getrefcount(a) Out[4]: 4 In [5]: ref=weakref.ref(a) In [6]: sys.getrefcount(a) Out[6]: 4weakref 的 ref 方法用于创建弱引用对象,它的返回值是引用指向的对象。函数定义如下:
weakref.ref(object[callback,])其中 object 即为被引用的对象,而 callback 是一个可选的回调函数。当引用的对象被删除的时候,回调函数就会被执行调用。通过 weakref.ref 创建的弱引用,在使用时需要使用 ref() 去获取 object:
In [1]: ref().hello() Out[2]: '新宝库'weakref 提供了 finalize 来定义引用对象被删除时执行的清理函数,它的定义如下:
finaiize(object,func,*args,**kwargs)其中,object 是引用的对象;func 是清理函数,obj 被删除时自动调用;*args 和 **kwargs 将会作为参数传递给清理函数。所以使用它的时候需要预先定义清理函数,示例如下:
In [9]: def func(obj): ...: print("%s被删除"%obj) ...: In [10]: weakref.finalize(a,func,str(hex(id(a)))) Out[10]: <finalize object at 0x508bd98; for 'A' at 0x85a7930> In [11]: del a 0x85a7930被删除这里还有一种特殊的情况即引用对象是对象实例的方法,此时不可以直接使用 weakref.ref 去创建弱引用,而是使用 weakref.WeakMethod(),示例如下:
In [14]: a=A() In [15]: ref=weakref.WeakMethod(a.hello)#引用对象a的hello方法 In [16]: ref()() Out[16]: '新宝库' In [17]: ref() Out[17]: <bound method A.hello of <__main__.A object at 0x05B64F30>>因为弱引用不会改变对象的引用计数,所以,Django 信号机制采用弱引用的方式对信号回调函数进行引用,以此来避免内存泄露的问题。
Django 信号机制涉及了诸多方面的知识,本节我们只是讲了你可能没有涉猎过的知识点,比如,Django 信号机制还应用了 Python 线程的同步机制,也就是使用锁即 Lock 来避免多线程程序中对共享资源的竞争导致的错误。在这里就不进行介绍了,有兴趣的同学可以自己探索。
所有教程
- C语言入门
- C语言编译器
- C语言项目案例
- 数据结构
- C++
- STL
- C++11
- socket
- GCC
- GDB
- Makefile
- OpenCV
- Qt教程
- Unity 3D
- UE4
- 游戏引擎
- Python
- Python并发编程
- TensorFlow
- Django
- NumPy
- Linux
- Shell
- Java教程
- 设计模式
- Java Swing
- Servlet
- JSP教程
- Struts2
- Maven
- Spring
- Spring MVC
- Spring Boot
- Spring Cloud
- Hibernate
- Mybatis
- MySQL教程
- MySQL函数
- NoSQL
- Redis
- MongoDB
- HBase
- Go语言
- C#
- MATLAB
- JavaScript
- Bootstrap
- HTML
- CSS教程
- PHP
- 汇编语言
- TCP/IP
- vi命令
- Android教程
- 区块链
- Docker
- 大数据
- 云计算