최상의 답변
위의 설명에 따르면 여기에 일반적인 전략이 있습니다. 당연히 세부 사항은 매우 중요합니다. .
기본적으로 두 부분으로 구성됩니다.
이벤트 개체 또는 “ 게시자”는 이벤트가 발생할 때 호출해야하는 모든 함수 목록을 유지합니다. 목록을 반복하고 모든 함수를 차례로 호출하는 fire()
메서드가 있습니다. 또한 목록을 관리하는 방법도 있어야합니다 (목록에서 함수를 제거하면 더 이상 필요하지 않습니다).
핸들러 또는 “ 구독자”는 이벤트가 실제로 발생할 때 호출 할 함수입니다. 유일하게 까다로운 부분은 이벤트가 추가 인트로 스펙 션을 수행하지 않고 호출 할 수 있도록 핸들러의 서명을 제어해야한다는 것입니다.
다음은 매우 간단한 예제입니다.
class Event(object):
def \_\_init\_\_(self, *args):
self.handlers = set()
self.args = args
def add(self, fn):
self.handlers.add(fn)
def remove(self, fn):
self.handlers.remove(fn)
def \_\_call\_\_(self, *args):
"""fire the event -- uses \_\_call\_\_ so we can just invoke the object directly..."""
runtime\_args = self.args + args
for each\_handler in self.handlers:
each\_handler(*runtime\_args)
class ExampleObject(object):
"""publish start and stop events"""
def \_\_init\_\_(self):
self.start = Event("started")
self.stop = Event("stopped")
def example\_handler(*args):
""" reacts to an event"""
print "example handler fired", args
fred = ExampleObject()
fred.start.add(example\_handler)
fred.stop.add(example\_handler)
fred.start()
fred.stop("optional extra arg")
생성해야합니다.
example handler fired ("started",)
example handler fired ("stopped", "optional extra arg")
주요 관리 문제는 다음과 같습니다.
예외 처리. 처리기가 예외로부터 안전해야하는지 여부를 결정해야합니다. 위의 코드가 어느 정도 괜찮지 않은 경우 “불량 가입자가 전체 프로그램을 중단하는 것을 원하지 않는 경우 예외에 대처하는 방법과 문제가되는 처리기를”구독 취소 “할지 여부를 결정해야합니다. .
메모리 관리. 이 예에서는 함수를 핸들러로만 사용합니다. 함수를 del () 할 필요가없는 경우 수명을 관리합니다. 그러나 종종 호출 가능한 객체 나 멤버 함수를 핸들러 / 구독자로 갖고 싶을 것입니다. 그렇다면 예제에 사용 된 순진한 집합보다는 약한 참조를 사용해야 할 것입니다. 그렇지 않으면 이벤트 핸들러가 객체가 범위를 벗어나야하고 가비지 수집되어야하는 후에도 객체를 살아있게 유지하게됩니다.
메타 데이터 : 이 예에는 Event()
가 선언됩니다. 애플리케이션에 이보다 더 많거나 적을 수 있습니다. 더 많은 메타 데이터는 일반적으로 더 많은 결합을 의미하며 이는 이상적이지 않습니다. 그러나 핸들러가 모두 (*args, **kwargs)
서명을 가지고있는 경우 언제든지 데이터를 전달한 다음 관심이 있는지 여부를 핸들러 수준에서 결정할 수 있습니다.
좋은 참조 : Python의 관찰자 패턴
기본 아이디어의 예 : theodox / mGui
Answer
토네이도 웹 프레임 워크 웹 사이트로 이동하면 예제 페이지가 있습니다. 이 페이지에는 예제 채팅 애플리케이션 코드가 있습니다. 매우 짧고 이해하기 쉽습니다.