V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
IurNusRay
V2EX  ›  Python

Django 中 Signal 的意义是什么

  •  
  •   IurNusRay · 2021-03-10 11:17:48 +08:00 · 2432 次点击
    这是一个创建于 1340 天前的主题,其中的信息可能已经有所发展或是发生改变。
    试了一下 Django 自带的 Signal 模块,也并不能异步啊,而且又是在框架内发送 /接收消息,那么它存在的意义就单纯是为了代码解耦吗?如果这样干嘛不直接写个普通函数呢..
    14 条回复    2021-03-31 17:49:07 +08:00
    twotiger
        1
    twotiger  
       2021-03-10 11:50:18 +08:00
    是的就是解耦。
    我个人也很少用到这个,不过之前的公司用来删除数据时,做一些操作。
    这种东西也就是一种设计模式,用好了,写的很好看,用的不好,还不如不写。
    xiaolinjia
        2
    xiaolinjia  
       2021-03-10 11:52:19 +08:00
    确实就是解耦,而之所以不写个普通函数,大概是因为传参很麻烦。
    GTim
        3
    GTim  
       2021-03-10 11:54:50 +08:00
    普通函数会涉及到声明的地方和调用的地方,这两者可能会高度耦合的。这边 import 一下 那边 import 一下。

    信号就不一样了,信号不用管谁接收,发出去即可。接收的地方也不用管谁发的,收到消息处理即可
    IurNusRay
        4
    IurNusRay  
    OP
       2021-03-10 12:53:55 +08:00
    @GTim 可是似乎用能信号来实现的功能,用普通函数来实现也可以啊,信号好像没没什么优势。比如我在收到客户端的点赞、评论、回复等请求的时候,要向指定用户发送消息提醒,那么我完全可以写一个公共函数,接收用户 id 、消息内容,然后发送消息,这个函数也可以在全局所有地方导入、调用,并没有什么缺点啊。。
    GeruzoniAnsasu
        5
    GeruzoniAnsasu  
       2021-03-10 12:57:41 +08:00   ❤️ 2
    想象一下 UI 编程。
    把 click 看成一个 signal,http 模块把现在文本框的内容 post 出去作为 slot

    显然在 button 的 onclick handler 里完全没必要实例化一个 http requester,从某个全局区获取一个 requester 再进行请求则更显怪异。优雅的做法当然是让 click 只作为一个信号灯,我们找一个第三者视角,看到灯亮的时候指使 http 模块发出请求。在第三者的上帝视角里能看到 button 的实例与 http 模块的实例,而 button 和 http 相互并不需要知道对方的实例存在。

    这是 qt 框架最基本的事件响应机制。基本上有 signal 这个概念的框架设计理念都是类似的。
    IurNusRay
        6
    IurNusRay  
    OP
       2021-03-10 13:10:16 +08:00
    @GeruzoniAnsasu 好像有点明白了,谢谢
    est
        7
    est  
       2021-03-10 13:16:37 +08:00
    > 如果这样干嘛不直接写个普通函数呢..

    因为你手上的业务不够多。。

    等你一个函数内部同时服务 3 、5 个需求方的时候,就知道麻烦了。
    coolair
        8
    coolair  
       2021-03-10 13:30:07 +08:00
    这个是我很喜欢 Django 的一点……太好用了,太方便了。
    2owe
        9
    2owe  
       2021-03-10 15:04:57 +08:00
    Signal,就是一种“注册-发布-订阅”的功能实现。

    Django 框架对外提供了一些信号,比如 post_save

    Ps. 想要异步的话,可以自己加 celery 改造
    23333333333
        10
    23333333333  
       2021-03-10 16:07:55 +08:00
    其实最大的作用就是解耦

    举个例:子 更新 cache

    * 有个函数去接 post_save 的信号,接到这个信号之后去删除对应的 cache,而不是每次手动去操作
    hj24
        11
    hj24  
       2021-03-10 16:14:59 +08:00
    确实只能解耦,你把代码写到一个函数里也是一样的,之前用 go 重构这种代码的时候基本都是写回到一个函数里
    acmore
        12
    acmore  
       2021-03-10 16:25:00 +08:00
    类似于(或者就是) Mediator pattern
    小项目用这个没有啥显著收益,直接普通函数完全没问题。
    大项目的好处楼上已经说得很全面了。

    但它会造成调用方和服务提供方在语法上的隔离,不是完美也不是唯一的方案。
    zachlhb
        13
    zachlhb  
       2021-03-10 18:14:24 +08:00 via iPhone
    逻辑解耦,比如完成一个操作后需要执行其他操作,而这些操作可能现在不确定或不是由你开发的,这时就需要用到信号,一个信号可以有多个接收者,这个很好管理,如果需要异步,可以在信号接收逻辑里派发异步任务
    zepc007
        14
    zepc007  
       2021-03-31 17:49:07 +08:00
    实际用处并不大,又不是异步,只不过是对数据处理提供一种 hook 方式
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2354 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 35ms · UTC 16:04 · PVG 00:04 · LAX 08:04 · JFK 11:04
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.