Skip to content

Instantly share code, notes, and snippets.

@azhai
Last active December 19, 2015 13:29
Show Gist options
  • Save azhai/5962735 to your computer and use it in GitHub Desktop.
Save azhai/5962735 to your computer and use it in GitHub Desktop.
Python信号与槽
"""
A signal/slot implementation
File: signal.py
Author: Thiago Marcos P. Santos
Author: Christopher S. Case
Author: David H. Bronke
Created: August 28, 2008
Updated: December 12, 2011
License: MIT
Url: http://code.activestate.com/recipes/577980-improved-signalsslots-implementation-in-python/
"""
from __future__ import print_function
import inspect
from weakref import WeakSet, WeakKeyDictionary
class Signal(object):
def __init__(self):
self._functions = WeakSet()
self._methods = WeakKeyDictionary()
def __call__(self, *args, **kargs):
# Call handler functions
for func in self._functions:
func(*args, **kargs)
# Call handler methods
for obj, funcs in self._methods.items():
for func in funcs:
func(obj, *args, **kargs)
def connect(self, slot):
if inspect.ismethod(slot):
if slot.__self__ not in self._methods:
self._methods[slot.__self__] = set()
self._methods[slot.__self__].add(slot.__func__)
else:
self._functions.add(slot)
def disconnect(self, slot):
if inspect.ismethod(slot):
if slot.__self__ in self._methods:
self._methods[slot.__self__].remove(slot.__func__)
else:
if slot in self._functions:
self._functions.remove(slot)
def clear(self):
self._functions.clear()
self._methods.clear()
# Sample usage:
if __name__ == '__main__':
class Model(object):
def __init__(self, value):
self.__value = value
self.changed = Signal()
def set_value(self, value):
self.__value = value
self.changed() # Emit signal
def get_value(self):
return self.__value
class View(object):
def __init__(self, model):
self.model = model
model.changed.connect(self.model_changed)
def model_changed(self):
print(" New value:", self.model.get_value())
print("Beginning Tests:")
model = Model(10)
view1 = View(model)
view2 = View(model)
view3 = View(model)
print("Setting value to 20...")
model.set_value(20)
print("Deleting a view, and setting value to 30...")
del view1
model.set_value(30)
print("Clearing all listeners, and setting value to 40...")
model.changed.clear()
model.set_value(40)
print("Testing non-member function...")
def bar():
print(" Calling Non Class Function!")
model.changed.connect(bar)
model.set_value(50)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment