Django信号机制源码分析(观察者模式)
Django信号的实现原理本质是设计模式中的观察者模式,浅谈Python设计模式 -- 观察者模式,也可以叫做发布-订阅模式,信号对象维护一个订阅者列表,当信号被触发时,它会遍历订阅者,依次通知它们。
先来回顾一下信号的定义和使用:
from django.dispatch import receiver, Signal# 信号定义
node_approved = Signal()# 信号的注册
@receiver(node_approved)
def on_node_approved(sender, instance, **kwargs):print(‘接收到信号’)# 信号的触发
node_approved.send(sender=xx, instance=yy)
源码分析:
1、先来看receiver这个装饰器:
def receiver(signal, **kwargs):"""A decorator for connecting receivers to signals. Used by passing in thesignal (or list of signals) and keyword arguments to connect::@receiver(post_save, sender=MyModel)def signal_receiver(sender, **kwargs):...@receiver([post_save, post_delete], sender=MyModel)def signals_receiver(sender, **kwargs):..."""def _decorator(func):if isinstance(signal, (list, tuple)):for s in signal:s.connect(func, **kwargs)else:signal.connect(func, **kwargs)return funcreturn _decorator
逻辑很简单的一个装饰器,核心是调用Signal信号对象的connect方法,也就是上面举例中的node_approved这个对象的connect方法。
2、接着看Signal 的connect方法:
class Signal:def __init__(self, providing_args=None, use_caching=False):"""Create a new signal."""self.receivers = []...def connect(self, receiver, sender=None, weak=True, dispatch_uid=None):from django.conf import settings# If DEBUG is on, check that we got a good receiverif settings.configured and settings.DEBUG:assert callable(receiver), "Signal receivers must be callable."# Check for **kwargsif not func_accepts_kwargs(receiver):raise ValueError("Signal receivers must accept keyword arguments (**kwargs).")if dispatch_uid:lookup_key = (dispatch_uid, _make_id(sender))else:lookup_key = (_make_id(receiver), _make_id(sender))if weak:ref = weakref.refreceiver_object = receiver# Check for bound methodsif hasattr(receiver, '__self__') and hasattr(receiver, '__func__'):ref = weakref.WeakMethodreceiver_object = receiver.__self__receiver = ref(receiver)weakref.finalize(receiver_object, self._remove_receiver)with self.lock:self._clear_dead_receivers()if not any(r_key == lookup_key for r_key, _ in self.receivers):self.receivers.append((lookup_key, receiver))self.sender_receivers_cache.clear()
只看倒数第二行:self.receivers.append((lookup_key, receiver)),如果你了解观察者模式就很好理解这行代码的意图:将被装饰的信号处理函数(on_node_approved)注册到self.recervers属性中,也就是观察者模式中讲的主题维护观察者列表行为。
一旦有了这个观察者列表,那么就很容易做到信号被触发时,通知每个观察者的目的。下面看看源码是怎么实现的:
3、信号触发send源码:
class Signal:def __init__(self, providing_args=None, use_caching=False):"""Create a new signal."""self.receivers = []...def _live_receivers(self, sender):"""Filter sequence of receivers to get resolved, live receivers.This checks for weak references and resolves them, then returning onlylive receivers."""...receivers = None...for (receiverkey, r_senderkey), receiver in self.receivers:if r_senderkey == NONE_ID or r_senderkey == senderkey:receivers.append(receiver)...non_weak_receivers = []for receiver in receivers:if isinstance(receiver, weakref.ReferenceType):# Dereference the weak reference.receiver = receiver()if receiver is not None:non_weak_receivers.append(receiver)else:non_weak_receivers.append(receiver)return non_weak_receiversdef send(self, sender, **named):if not self.receivers or self.sender_receivers_cache.get(sender) is NO_RECEIVERS:return []return [(receiver, receiver(signal=self, sender=sender, **named))for receiver in self._live_receivers(sender)]
send理解起来也不难:遍历self._live_receivers(),依次调用各个receiver。而_live_receivers通过源码也可以看出本质还是遍历前面提到的观察者列表self.recervers属性。
相关文章:
Django信号机制源码分析(观察者模式)
Django信号的实现原理本质是设计模式中的观察者模式,浅谈Python设计模式 -- 观察者模式,也可以叫做发布-订阅模式,信号对象维护一个订阅者列表,当信号被触发时,它会遍历订阅者,依次通知它们。 先来回顾一下…...
MyBatis-config.xml配置文件
1、基本介绍: mybatis的核心配置文件(mybatis-config.xml),比如配置jdbc连接信息,注册mapper等等,我们需要对这个配置文件有详细的了解。 官网地址有详细介绍 mybatis – MyBatis 3 | 配置 2、properties属性 在通常的情况下&am…...
【Spring实战】17 REST服务介绍
文章目录 1. 为什么出现2. 拥有哪些优势3. Spring中的应用4. spring-boot-starter-data-rest总结 REST(Representational State Transfer)是一种软件架构风格,通常用于设计网络应用程序的服务接口。RESTful 服务是基于 REST 原则构建的网络服…...
java struts2教务管理系统Myeclipse开发mysql数据库struts2结构java编程计算机网页项目
一、源码特点 java struts2 教务管理系统 是一套完善的web设计系统,对理解JSP java编程开发语言有帮助 struts2 框架开发,系统具有完整的源代码和数据库,系统主要采用B/S模式开发。开发环境 为TOMCAT7.0,Myeclipse8.5开发,数据库…...
跟着cherno手搓游戏引擎【3】事件系统和预编译头文件
不多说了直接上代码,课程中的架构讲的比较宽泛,而且有些方法写完之后并未测试。所以先把代码写完。理解其原理,未来使用时候会再此完善此博客。 文件架构: Event.h:核心基类 #pragma once #include"../Core.h" #inclu…...
排序算法之快速排序
快速排序是一种高效的排序算法,它的基本思想是采用分治策略,将一个无序数组分割成两个子数组,分别对子数组进行排序,然后将两个排序好的子数组合并成一个有序数组。快速排序的性能优于归并排序,尤其在处理大规模数据时…...
Docker 从入门到实践:Docker介绍
前言 在当今的软件开发和部署领域,Docker已经成为了一个不可或缺的工具。Docker以其轻量级、可移植性和标准化等特点,使得应用程序的部署和管理变得前所未有的简单。无论您是一名开发者、系统管理员,还是IT架构师,理解并掌握Dock…...
用IDEA创建/同步到gitee(码云)远程仓库(保姆级详细)
前言: 笔者最近在学习java,最开始在用很笨的方法:先克隆远程仓库到本地,再把自己练习的代码从本地仓库上传到远程仓库,很是繁琐。后发现可以IDEA只需要做些操作可以直接把代码上传到远程仓库,也在网上搜了些…...
【Linux】进程控制深度了解
> 作者简介:დ旧言~,目前大二,现在学习Java,c,c,Python等 > 座右铭:松树千年终是朽,槿花一日自为荣。 > 目标:熟练掌握Linux下的进程控制 > 毒鸡汤ÿ…...
kbdnso.dll文件缺失,软件或游戏报错的快速修复方法
很多小伙伴遇到电脑报错,提示“kbdnso.dll文件缺失,程序无法启动执行”时,不知道应该怎样处理,还以为是程序出现了问题,想卸载重装。 首先,先要了解“kbdnso.dll文件”是什么? kbdnso.dll是Win…...
Spring技术内幕笔记之IOC的实现
IOC容器的实现 依赖反转: 依赖对象的获得被反转了,于是依赖反转更名为:依赖注入。许多应用都是由两个或者多个类通过彼此的合作来实现业务逻辑的,这使得每个对象都需要与其合作的对象的引用,如果这个获取过程需要自身…...
kotlin foreach 循环
java中的foreach循环也使用于kotlin ,先回顾下java里面的foreach循环 java foreach循环格式 for(元素类型t 元素变量x : 遍历对象obj){引用了x的语句;} 例如: int[] intary {1,2,3,4};for (int a: intary) {Log.d("intary", String.value…...
分享相关知识
直接使用海龟图进行创作移动动态的游戏 这段代码是一个简单的turtle模块实现的小游戏,主要功能包括: 窗口和无人机初始化: 创建了一个turtle窗口,设置了窗口的背景颜色和标题。创建了一个表示无人机的turtle,形状为正…...
RabbitMQ(七)ACK 消息确认机制
目录 一、简介1.1 背景1.2 定义1.3 如何查看确认/未确认的消息数? 二、消息确认机制的分类2.1 消息发送确认1)ConfirmCallback方法2)ReturnCallback方法3)代码实现方式一:统一配置a.配置类a.生产者c.消费者d.测试结果 …...
ubuntu 编译内核报错
Ubuntu 编译 Linux 内核经常会遇到如下错误: 如果报错 canonical-certs.pem: 如下: make[1]: *** No rule to make target ‘debian/canonical-certs.pem’, needed by ‘certs/x509_certificate_list’. Stop. make: *** [Makefile:1868: …...
Python之自然语言处理库snowNLP
一、介绍 SnowNLP是一个python写的类库,可以方便的处理中文文本内容,是受到了TextBlob的启发而写的,由于现在大部分的自然语言处理库基本都是针对英文的,于是写了一个方便处理中文的类库,并且和TextBlob不同的是&…...
C# 语法进阶 委托
1.委托 委托是一个引用类型,其实他是一个类,保存方法的指针 (指针:保存一个变量的地址)他指向一个方法,当我们调用委托的时候这个方法就立即被执行 关键字:delegate 运行结果: 思…...
开源可观测性平台Signoz(四)【链路监控及数据库中间件监控篇】
转载说明:如果您喜欢这篇文章并打算转载它,请私信作者取得授权。感谢您喜爱本文,请文明转载,谢谢。 前文链接: 开源可观测性平台Signoz系列(一)【开篇】 开源可观测性平台Signoz&…...
【嵌入式开发 Linux 常用命令系列 4.2 -- git .gitignore 使用详细介绍】
文章目录 .gitignore 使用详细介绍.gitignore 文件的位置.gitignore 语法规则使用示例注意事项 .gitignore 使用详细介绍 .gitignore 文件是一个特殊的文本文件,它告诉 Git 哪些文件或目录是可以被忽略的,即不应该被纳入版本控制系统。这主要用于避免一…...
【熔断限流组件resilience4j和hystrix】
文章目录 🔊博主介绍🥤本文内容起因resilience4j落地实现pom.xml依赖application.yml配置接口使用 hystrix 落地实现pom.xml依赖启动类上添加注解接口上使用 📢文章总结📥博主目标 🔊博主介绍 🌟我是廖志伟…...
对比直接使用官方API,通过Taotoken调用大模型的实际费用观察
🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 对比直接使用官方API,通过Taotoken调用大模型的实际费用观察 1. 引言 在项目开发中,大模型API的调用成本是…...
Mobocertinib莫博赛替尼副作用恶心及口腔炎如何有效处理【海得康】
在莫博替尼(Mobocertinib,商品名Exkivity)治疗EGFR外显子20插入突变非小细胞肺癌的临床实践中,恶心与口腔炎是两类最令患者苦不堪言的不良反应。它们不像腹泻那样来势汹涌、立竿见影,却以一种持续而隐蔽的方式侵蚀着患…...
响应式编程-Flux 背压机制与操作符链式调用源码剖析
1. Flux背压机制的核心原理 背压(Backpressure)是响应式编程中最重要的流量控制机制之一。想象一下自来水管和水龙头的关系:当水龙头开得太大而下水道排水速度跟不上时,水槽就会溢出。Flux的背压机制就像这个系统中的智能调节阀&…...
基于Vue 3与TypeScript的Dify AI聊天前端开发与部署实战
1. 项目概述:一个现代化的Dify AI聊天前端 如果你正在寻找一个开箱即用、界面美观且功能完整的Dify AI聊天前端,那么LeeAirQ/Dify-Web这个项目值得你花时间了解一下。作为一个长期在AI应用层折腾的开发者,我见过太多后端强大但前端简陋的AI项…...
UHP驱动器热管理:Flotherm仿真与优化实践
1. UHP高电流驱动器热设计挑战在投影仪用超高压(UHP)灯驱动器的开发中,热管理始终是制约产品小型化和功率提升的关键瓶颈。飞利浦工业技术中心的案例显示,当驱动器体积从150x73x32mm缩减到120x41x24mm时,功率密度从0.02mW/mm激增至0.18mW/mm—…...
【信息科学与工程学】计算机科学与自动化——第一百五十一篇 云计算操作系统函数说明02
威胁情报与狩猎模块(361-370) 编号 模块/组件类型 模块中的函数名称和函数的参数列表和函数的实现方式 函数的详细功能和计算机科学的所有性能【含参数列表】和功能说明 关联的其他函数【含上下文关系】 和对应模块【含上下文关系】 关联的软件/硬件核心知识点【需要涵…...
告别CNN!用PyG Temporal和GC-LSTM搞定动态社交网络的好友推荐(附完整代码)
动态社交网络好友推荐的工程实践:基于GC-LSTM与PyG Temporal的完整解决方案 社交网络的动态特性为传统推荐系统带来了巨大挑战。当用户关系每分每秒都在变化时,静态的协同过滤或内容推荐方法往往显得力不从心。本文将分享如何利用PyG Temporal库和GC-LST…...
基于MCP协议构建团队AI共享记忆中枢:Trapic项目实战指南
1. 项目概述:为团队AI工具构建共享记忆中枢 如果你和你的团队在日常开发中,已经习惯了与Claude Code、Cursor这类AI编程助手进行深度对话,那么一个共同的痛点可能已经浮现:每次开启一个新的会话,AI助手都像一张白纸&a…...
Android Studio中文界面终极指南:3分钟告别英文开发困境
Android Studio中文界面终极指南:3分钟告别英文开发困境 【免费下载链接】AndroidStudioChineseLanguagePack AndroidStudio中文插件(官方修改版本) 项目地址: https://gitcode.com/gh_mirrors/an/AndroidStudioChineseLanguagePack 还在为Androi…...
AMD锐龙SMU调试工具:从新手到专家的完整调优指南
AMD锐龙SMU调试工具:从新手到专家的完整调优指南 【免费下载链接】SMUDebugTool A dedicated tool to help write/read various parameters of Ryzen-based systems, such as manual overclock, SMU, PCI, CPUID, MSR and Power Table. 项目地址: https://gitcode…...
