O que é programação orientada a eventos boa e limpa em Python? No momento, estou enfrentando o que é chamado de ' Inferno de retorno de chamada ' e quero saber como fazê-lo direito.


Melhor resposta

Com base nos comentários acima, aqui está uma estratégia geral. Obviamente, os detalhes importam muito, é claro .

Basicamente, você terá duas partes.

O objeto de evento ou o “ editor” é responsável por mantendo uma lista de todas as funções que devem ser chamadas quando um evento acontece. Ele tem um método fire() que percorre essa lista e chama todas as funções sucessivamente. Provavelmente também deve ter métodos para gerenciar a lista (removendo uma função da lista que não é mais necessária).

Os manipuladores ou “ assinantes” são funções que você vai chamar quando o evento realmente acontecer. A única coisa complicada é que você precisa controlar a assinatura dos manipuladores para que o evento possa chamá-los sem fazer nenhuma introspecção extra.

Aqui está um exemplo ultramínimo:

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")

Isso deve produzir

example handler fired ("started",)

example handler fired ("stopped", "optional extra arg")

Os principais problemas de gerenciamento são:

Tratamento de exceções. você precisa decidir se o manipulador deve ser seguro para exceções ou não. Se não, o código acima está mais ou menos OK, mas se você não quer que um assinante ruim desative todo o programa, você precisa decidir como lidar com uma exceção e se deve ou não “cancelar a assinatura” do manipulador infrator .

Gerenciamento de memória. O exemplo usa apenas uma função como um manipulador; a menos que você del () a função, você não precisa gerencie sua vida útil. No entanto, você frequentemente desejará ter objetos que podem ser chamados ou funções de membro como manipuladores / assinantes. Em caso afirmativo, você provavelmente precisará usar referências fracas em vez do conjunto ingênuo usado no exemplo – caso contrário, os manipuladores de eventos acabarão mantendo os objetos vivos depois que eles deveriam ter saído do escopo e deveriam ser coletados como lixo.

Metadados: o exemplo inclui um pouco de metadados – a string que é passada como Event() s são declarados. Seu aplicativo pode precisar de mais ou menos do que isso. Mais metadados geralmente significam mais acoplamento, o que não é o ideal. No entanto, se todos os seus gerenciadores tiverem a assinatura (*args, **kwargs) , você sempre pode passar os dados e decidir no nível do gerenciador se você se importa com isso ou não.

Boa referência : O padrão do observador em Python

Exemplo da ideia básica em ação: teodoxo / mGui

Resposta

Se você for ao site da estrutura da web do tornado, há uma página de exemplos. Nessa página, há um exemplo de código de aplicativo de bate-papo. É extremamente curto e compreensível.

Deixe uma resposta

O seu endereço de email não será publicado. Campos obrigatórios marcados com *