python处理信号机制_python:signal/slot机制

观察者模式

观察者模式是软件设计模式的一种。在此种模式中,一个目标对象管理所有相依于它的观察者对象,并且在它本身的状态改变时主动发出通知。这通常透过呼叫各观察者所提供的方法来实现。此种模式通常被用来实时事件处理系统

观察者模式观察者模式结构如下:

observer

分析

根据其定义可以得出几条重要的结论:

目标对象会保存其订阅者的引用

状态改变,即满足条件时,目标会拿到订阅者的引用,并且调用订阅者的方法接口

Observer是观察者的接口,提供notify接口,由Subject来调用,由具体的concreteObserver实现。

Subject是订阅的主题,提供3个接口,通知、增加订阅者和删除订阅者。

贴出维基上Python的实现:

class AbstractSubject(object):

def register(self, listener):

raise NotImplementedError("Must subclass me")

def deregister(self, listener):

raise NotImplementedError("Must subclass me")

def notify_listeners(self, event):

raise NotImplementedError("Must subclass me")

class Listener(object):

def __init__(self, name, subject):

self.name = name

subject.register(self)

def notify(self, event):

print self.name, "received event", event

class Subject(AbstractSubject):

def __init__(self):

self.listeners = []

self.data = None

def getUserAction(self):

self.data = raw_input('Enter something to do:')

return self.data

# Implement abstract Class AbstractSubject

def register(self, listener):

self.listeners.append(listener)

def deregister(self, listener):

self.listeners.remove(listener)

def notify_listeners(self, event):

for listener in self.listeners:

listener.notify(event)

if __name__=="__main__":

# make a subject object to spy on

subject = Subject()

# register two listeners to monitor it.

listenerA = Listener("", subject)

listenerB = Listener("", subject)

# simulated event

subject.notify_listeners ("")

# outputs:

# received event

# received event

action = subject.getUserAction()

subject.notify_listeners(action)

#Enter something to do:hello

# outputs:

# received event hello

# received event hello

signal/slot 信号槽

信号槽似乎来源于QT,相关介绍qt信号槽,其结构是所有的控件都继承自signalApp,signalApp实现了3个通用接口,产生信号、产生槽和连接信号和槽

信号和槽的关系

当信号发送出去时,会调用信号相关联的槽函数。比如:

button = Button()

lable = Label()

signalAPP.connect(button, SIGNAL(clicked), lable, SLOT(setValue))

将button的点击信号和label的槽函数进行连接,当信号发送时,会调用label的槽函数,这种机制将信号与槽分离,可以信号与信号进行连接,可以一个信号对应多个槽,可以一个槽对应多个信号。

一个简单的python信号槽实现

# -*- coding: utf-8 -*-

class CSignal():

def __init__(self):

self.slot = []

def emit(self, *arg, **kw):

for pFunc in self.slot:

pFunc(*arg, **kw)

def connect(self, cbfunc):

self.slot.append(cbfunc)

class memberFuc():

def __init__(self):

pass

def test(self, *arg, **kw):

print 'i am memberFuc!'

def test(*arg, **kw):

print "i am test", arg, kw

if __name__ == "__main__":

testSignal = CSignal()

testSignal.connect(test)

testOb = memberFuc()

testSignal.connect(testOb.test)

testSignal.emit()

# output:

# i am test

# i am memberfunc

del testOb

testSignal.emit()

# output:

# i am test

# i am memberfunc

上面代码和QT的信号槽有几点不同:

一个信号只关联一个槽

信号对象独立出来,不是控件的基类

注意:当connect一个method时,会增加对象的引用计数,导致del 对象时,对象引用计数不为0,仍然存在,解决的方法时利用弱引用。下面是网上的实现:

"""

File: signals.py

Author: Patrick Chasco

Created: July 26, 2005

Purpose: A signals implementation

"""

#========================================================

# Implementation

#========================================================

from weakref import *

import inspect

class Signal:

"""

class Signal

A simple implementation of the Signal/Slot pattern. To use, simply

create a Signal instance. The instance may be a member of a class,

a global, or a local; it makes no difference what scope it resides

within. Connect slots to the signal using the "connect()" method.

The slot may be a member of a class or a simple function. If the

slot is a member of a class, Signal will automatically detect when

the method's class instance has been deleted and remove it from

its list of connected slots.

"""

def __init__(self):

self.slots = []

# for keeping references to _WeakMethod_FuncHost objects.

# If we didn't, then the weak references would die for

# non-method slots that we've created.

self.funchost = []

def __call__(self, *args, **kwargs):

for i in range(len(self.slots)):

slot = self.slots[i]

if slot != None:

slot(*args, **kwargs)

else:

del self.slots[i]

def call(self, *args, **kwargs):

self.__call__(*args, **kwargs)

def connect(self, slot):

self.disconnect(slot)

if inspect.ismethod(slot):

self.slots.append(WeakMethod(slot))

else:

o = _WeakMethod_FuncHost(slot)

self.slots.append(WeakMethod(o.func))

# we stick a copy in here just to keep the instance alive

self.funchost.append(o)

def disconnect(self, slot):

try:

for i in range(len(self.slots)):

wm = self.slots[i]

if inspect.ismethod(slot):

if wm.f == slot.im_func and wm.c() == slot.im_self:

del self.slots[i]

return

else:

if wm.c().hostedFunction == slot:

del self.slots[i]

return

except:

pass

def disconnectAll(self):

del self.slots

del self.funchost

self.slots = []

self.funchost = []

class _WeakMethod_FuncHost:

def __init__(self, func):

self.hostedFunction = func

def func(self, *args, **kwargs):

self.hostedFunction(*args, **kwargs)

# this class was generously donated by a poster on ASPN (aspn.activestate.com)

class WeakMethod:

def __init__(self, f):

self.f = f.im_func

self.c = ref(f.im_self)

def __call__(self, *args, **kwargs):

if self.c() == None : return

self.f(self.c(), *args, **kwargs)

#========================================================

# Example usage

#========================================================

if __name__ == "__main__":

class Button:

def __init__(self):

# Creating a signal as a member of a class

self.sigClick = Signal()

class Listener:

# a sample method that will be connected to the signal

def onClick(self):

print "onClick ", repr(self)

# a sample function to connect to the signal

def listenFunction():

print "listenFunction"

# a function that accepts arguments

def listenWithArgs(text):

print "listenWithArgs: ", text

b = Button()

l = Listener()

# Demonstrating connecting and calling signals

print

print "should see one message"

b.sigClick.connect(l.onClick)

b.sigClick()

# Disconnecting all signals

print

print "should see no messages"

b.sigClick.disconnectAll()

b.sigClick()

# connecting multiple functions to a signal

print

print "should see two messages"

l2 = Listener()

b.sigClick.connect(l.onClick)

b.sigClick.connect(l2.onClick)

b.sigClick()

# disconnecting individual functions

print

print "should see two messages"

b.sigClick.disconnect(l.onClick)

b.sigClick.connect(listenFunction)

b.sigClick()

# signals disconnecting automatically

print

print "should see one message"

b.sigClick.disconnectAll()

b.sigClick.connect(l.onClick)

b.sigClick.connect(l2.onClick)

del l2

b.sigClick()

# example with arguments and a local signal

print

print "should see one message"

sig = Signal()

sig.connect(listenWithArgs)

sig("Hello, World!")

参考

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值