Также было бы полезно рассмотреть то, что они делают с семантической точки зрения:
will assign the values of the properties of its second parameter and so on,
as properties with the same name of the first parameter. (shallow copy & override)
merge is like assign but does not assign objects but replicates them instead.
(deep copy)
provides default values for missing values.
so will assign only values for keys that do not exist yet in the source.
works like _defaults but like merge will not simply copy objects
and will use recursion instead.
Я считаю, что научиться думать об этих методах с семантической точки зрения позволит вам лучше «угадать», что будет поведение для всех различных сценариев существующих и несуществующих ценностей.
Вот еще один модуль для рассмотрения. Этот вариант подходит для более требовательных приложений.
Py-notify - это пакет Python. предоставление инструментов для реализации Шаблон программирования наблюдателя. Эти инструменты включают сигналы, условия и переменные.
Сигналы - это списки обработчиков, которые вызывается, когда издается сигнал. Условия в основном логические переменные вместе с сигналом, который излучается, когда состояние состояния изменения. Их можно комбинировать с помощью стандартные логические операторы (не, и, др.) в сложные условия. Переменные, в отличие от условий, могут иметь любой объект Python, а не только логические, но их нельзя объединить.
Я использую zope.event . Это самые голые кости, которые вы можете себе представить. :-) Фактически, вот полный исходный код:
subscribers = []
def notify(event):
for subscriber in subscribers:
subscriber(event)
Обратите внимание, что, например, вы не можете отправлять сообщения между процессами. Это не система обмена сообщениями, просто система событий, ни больше, ни меньше.
Я нашел этот небольшой сценарий на Ценных уроках . Кажется, у него как раз то, что мне нужно, соотношение простота / мощность. Питер Тэтчер является автором следующего кода (лицензирование не упоминается).
class Event:
def __init__(self):
self.handlers = set()
def handle(self, handler):
self.handlers.add(handler)
return self
def unhandle(self, handler):
try:
self.handlers.remove(handler)
except:
raise ValueError("Handler is not handling this event, so cannot unhandle it.")
return self
def fire(self, *args, **kargs):
for handler in self.handlers:
handler(*args, **kargs)
def getHandlerCount(self):
return len(self.handlers)
__iadd__ = handle
__isub__ = unhandle
__call__ = fire
__len__ = getHandlerCount
class MockFileWatcher:
def __init__(self):
self.fileChanged = Event()
def watchFiles(self):
source_path = "foo"
self.fileChanged(source_path)
def log_file_change(source_path):
print "%r changed." % (source_path,)
def log_file_change2(source_path):
print "%r changed!" % (source_path,)
watcher = MockFileWatcher()
watcher.fileChanged += log_file_change2
watcher.fileChanged += log_file_change
watcher.fileChanged -= log_file_change2
watcher.watchFiles()
Если я пишу код в pyQt, я использую парадигму сокетов / сигналов QT, то же самое для django
Если Я выполняю асинхронный ввод-вывод. Я использую собственный модуль выбора
. Если я использую синтаксический анализатор SAX python, я использую API событий, предоставляемый SAX. Похоже, я стал жертвой базового API: -)
Может быть, вам стоит спросить себя, чего вы ждете от фреймворка / модуля событий. Лично я предпочитаю использовать парадигму Socket / Signal от QT. дополнительную информацию об этом можно найти здесь
Мы используем EventHook, как это было предложено Майклом Фурдом в его Шаблон событий :
Просто добавьте EventHooks в свои классы с помощью:
class MyBroadcaster()
def __init__():
self.onChange = EventHook()
theBroadcaster = MyBroadcaster()
# add a listener to the event
theBroadcaster.onChange += myFunction
# remove listener from the event
theBroadcaster.onChange -= myFunction
# fire event
theBroadcaster.onChange.fire()
Мы добавили функциональность для удаления всех прослушивателей из объекта в класс Michaels и получили следующее:
class EventHook(object):
def __init__(self):
self.__handlers = []
def __iadd__(self, handler):
self.__handlers.append(handler)
return self
def __isub__(self, handler):
self.__handlers.remove(handler)
return self
def fire(self, *args, **keywargs):
for handler in self.__handlers:
handler(*args, **keywargs)
def clearObjectHandlers(self, inObject):
for theHandler in self.__handlers:
if theHandler.im_self == inObject:
self -= theHandler
Я делал это так:
class Event(list):
"""Event subscription.
A list of callable objects. Calling an instance of this will cause a
call to each item in the list in ascending order by index.
Example Usage:
>>> def f(x):
... print 'f(%s)' % x
>>> def g(x):
... print 'g(%s)' % x
>>> e = Event()
>>> e()
>>> e.append(f)
>>> e(123)
f(123)
>>> e.remove(f)
>>> e()
>>> e += (f, g)
>>> e(10)
f(10)
g(10)
>>> del e[0]
>>> e(2)
g(2)
"""
def __call__(self, *args, **kwargs):
for f in self:
f(*args, **kwargs)
def __repr__(self):
return "Event(%s)" % list.__repr__(self)
Однако, как и во всем остальном, что я видел, для этого нет ни авто-генерируемого пидока, ни подписей, что действительно отстойно.