摘要:的信號機制就是基于它建立的。觸發(fā)信號使用方法通知信號訂閱者。每個元組的組成為。與是兩個不同的信號。這時,可以使用優(yōu)化信號發(fā)送信號通常會進(jìn)行優(yōu)化,以便快速的發(fā)送。
參考 Blinker Documentation
Blinker 是一個基于Python的強大的信號庫,它既支持簡單的對象到對象通信,也支持針對多個對象進(jìn)行組播。Flask的信號機制就是基于它建立的。
Blinker的內(nèi)核雖然小巧,但是功能卻非常強大,它支持以下特性:
支持注冊全局命名信號
支持匿名信號
支持自定義命名信號
支持與接收者之間的持久連接與短暫連接
通過弱引用實現(xiàn)與接收者之間的自動斷開連接
支持發(fā)送任意大小的數(shù)據(jù)
支持收集信號接收者的返回值
線程安全
創(chuàng)建信號信號通過signal()方法進(jìn)行創(chuàng)建:
>>> from blinker import signal >>> initialized = signal("initialized") >>> initialized is signal("initialized") True
每次調(diào)用signal("name")都會返回同一個信號對象。因此這里signal()方法使用了單例模式。
訂閱信號使用Signal.connect()方法注冊一個函數(shù),每當(dāng)觸發(fā)信號的時候,就會調(diào)用該函數(shù)。該函數(shù)以觸發(fā)信號的對象作為參數(shù),這個函數(shù)其實就是信號訂閱者。
>>> def subscriber(sender): ... print("Got a signal sent by %r" % sender) ... >>> ready = signal("ready") >>> ready.connect(subscriber)觸發(fā)信號
使用Signal.send()方法通知信號訂閱者。
下面定義類Processor,在它的go()方法中觸發(fā)前面聲明的ready信號,send()方法以self為參數(shù),也就是說Processor的實例是信號的發(fā)送者。
>>> class Processor: ... def __init__(self, name): ... self.name = name ... ... def go(self): ... ready = signal("ready") ... ready.send(self) ... print("Processing.") ... complete = signal("complete") ... complete.send(self) ... ... def __repr__(self): ... return "" % self.name ... >>> processor_a = Processor("a") >>> processor_a.go() Got a signal sent by Processing.
注意到go()方法中的complete信號沒?并沒有訂閱者訂閱該信號,但是依然可以觸發(fā)該信號。如果沒有任何訂閱者的信號,結(jié)果是什么信號也不會發(fā)送,而且Blinker內(nèi)部對這種情況進(jìn)行了優(yōu)化,以盡可能的減少內(nèi)存開銷。
訂閱特定的發(fā)布者默認(rèn)情況下,任意發(fā)布者觸發(fā)信號,都會通知訂閱者。可以給Signal.connect()傳遞一個可選的參數(shù),以便限制訂閱者只能訂閱特定發(fā)送者。
>>> def b_subscriber(sender): ... print("Caught signal from processor_b.") ... assert sender.name == "b" ... >>> processor_b = Processor("b") >>> ready.connect(b_subscriber, sender=processor_b)
現(xiàn)在訂閱者只訂閱了processor_b發(fā)布的ready信號:
>>> processor_a.go() Got a signal sent by通過信號收發(fā)數(shù)據(jù)Processing. >>> processor_b.go() Got a signal sent by Caught signal from processor_b. Processing.
可以給send()方法傳遞額外的關(guān)鍵字參數(shù),這些參數(shù)會傳遞給訂閱者。
>>> send_data = signal("send-data") >>> @send_data.connect ... def receive_data(sender, **kw): ... print("Caught signal from %r, data %r" % (sender, kw)) ... return "received!" ... >>> result = send_data.send("anonymous", abc=123) Caught signal from "anonymous", data {"abc": 123}
send()方法的返回值收集每個訂閱者的返回值,拼接成一個元組組成的列表。每個元組的組成為(receiver function, return value)。
匿名信號前面我們創(chuàng)建的信號都是命名信號,每次調(diào)用Signal構(gòu)造器都會創(chuàng)建一個唯一的信號,,也就是說每次創(chuàng)建的信號是不一樣的。下面對前面的Processor類進(jìn)行改造,將signal作為它的類屬性。
>>> from blinker import Signal >>> class AltProcessor: ... on_ready = Signal() ... on_complete = Signal() ... ... def __init__(self, name): ... self.name = name ... ... def go(self): ... self.on_ready.send(self) ... print("Alternate processing.") ... self.on_complete.send(self) ... ... def __repr__(self): ... return "" % self.name ...
上面創(chuàng)建的就是匿名信號。on_ready與on_complete是兩個不同的信號。
使用修飾器訂閱信號除了使用connect()方法訂閱信號之外,使用@connect修飾器可以達(dá)到同樣的效果。
>>> apc = AltProcessor("c") >>> @apc.on_complete.connect ... def completed(sender): ... print "AltProcessor %s completed!" % sender.name ... >>> apc.go() Alternate processing. AltProcessor c completed!
盡管這樣用起來很方便,但是這種形式不支持訂閱指定的發(fā)送者。這時,可以使用connect_via():
>>> dice_roll = signal("dice_roll") >>> @dice_roll.connect_via(1) ... @dice_roll.connect_via(3) ... @dice_roll.connect_via(5) ... def odd_subscriber(sender): ... print("Observed dice roll %r." % sender) ... >>> result = dice_roll.send(3) Observed dice roll 3.優(yōu)化信號發(fā)送
信號通常會進(jìn)行優(yōu)化,以便快速的發(fā)送。不管有沒有訂閱者,都可以發(fā)送信號。如果發(fā)送信號時需要傳送的參數(shù)要計算很長時間,可以在發(fā)送之前使用receivers屬性先檢查一下是否有訂閱者。
>>> bool(signal("ready").receivers) True >>> bool(signal("complete").receivers) False >>> bool(AltProcessor.on_complete.receivers) True
還可以檢查訂閱者是否訂閱了某個具體的信號發(fā)布者。
>>> signal("ready").has_receivers_for(processor_a) True
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/38026.html
摘要:下面是演示視頻物聯(lián)網(wǎng)文章目錄前言一準(zhǔn)備二操作步驟配置配置三效果展示總結(jié)前言實現(xiàn)萬物互聯(lián)第一步,千里點燈,然后添加你想要的模塊就可以了,接下來我們進(jìn)入正文。 前面學(xué)習(xí)...
摘要:紅外模塊接入板子后,可進(jìn)行以上操作,并接入,通過控制空調(diào)。材料清單板子紅外接收模塊紅外發(fā)射模塊線杜邦線左邊是紅外發(fā)射模塊,右邊是紅外接收模塊。 錯開の折騰經(jīng)歷:ES...
摘要:錯開折騰經(jīng)歷文章目錄前言思路設(shè)備配置程序代碼小愛訓(xùn)練測試總結(jié)前言之前已經(jīng)進(jìn)行了項目二接入小愛同學(xué)以及項目三空調(diào)控制,接下來便是將二者合一,實現(xiàn)控制,溫濕度查看,以及小愛同學(xué)進(jìn)行簡單空調(diào)控制。 ...
摘要:單元測試這個應(yīng)用非常小以至于不需要太多的測試,但是作為示例會在示例中展示兩個簡單的測試定義。示例單元測試編寫好的測試使用的是來自于標(biāo)準(zhǔn)庫中標(biāo)準(zhǔn)的包。為了運行單元測試,可以在腳本中增加一個自定義的命令。 4、啟動腳本 頂層目錄中的manage.py文件用于啟動應(yīng)用。這個腳本會在示例7-8中展示。 示例7-8. manage.py:啟動腳本 #!/usr/bin/env python im...
摘要:問題描述我在學(xué)習(xí)的時候想嘗試一下物聯(lián)網(wǎng)的使用,在調(diào)用官方的例程的時候發(fā)現(xiàn)程序編譯出現(xiàn)了問題上圖中的對應(yīng)多個庫沒有問題,對實際編譯無影響。主要是出現(xiàn)了這個問題上圖中是的編譯器,出現(xiàn)問題是因為編譯器把一些警告當(dāng)成錯誤了。再次編譯,編譯成功 問題描述: ? ? ? ? 我在學(xué)習(xí)esp32的時候想嘗...
閱讀 3869·2023-04-26 00:36
閱讀 2676·2021-11-16 11:44
閱讀 1102·2021-11-15 17:58
閱讀 1674·2021-09-30 09:47
閱讀 1216·2019-08-30 13:05
閱讀 1550·2019-08-30 12:55
閱讀 2417·2019-08-30 11:02
閱讀 2739·2019-08-29 17:01