4 votes

d'autres façons d'implémenter le modèle de l'observateur en python

J'étais en train de parcourir un poste poste sur la façon dont le modèle de l'observateur peut être mis en œuvre en python. sur le même post, il y a ces commentaires.

1) En Python, vous pouvez tout aussi bien utiliser de simples fonctions, n'est pas vraiment nécessaire.

2) C'est un excellent exemple de ce que les programmeurs Java essaient de faire lorsque une fois qu'ils sont passés à Python - le et essaient de les "porter".

Ces commentaires impliquent que le pattern observateur n'est pas vraiment utile en Python et qu'il existe d'autres moyens d'obtenir le même effet. est-ce vrai et si oui, comment peut-on faire ?

Voici le code du modèle d'observateur :

class Observable(object):

    def __init__(self):
        self.observers = []

    def register(self, observer):
        if not observer in self.observers:
            self.observers.append(observer)

    def unregister(self, observer):
        if observer in self.observers:
            self.observers.remove(observer)

    def unregister_all(self):
        if self.observers:
            del self.observers[:]

    def update_observers(self, *args, **kwargs):
        for observer in self.observers:
            observer.update(*args, **kwargs)

from abc import ABCMeta, abstractmethod

class Observer(object):
    __metaclass__ = ABCMeta

    @abstractmethod
    def update(self, *args, **kwargs):
        pass

class AmericanStockMarket(Observer):
    def update(self, *args, **kwargs):
        print("American stock market received: {0}\n{1}".format(args, kwargs))

class EuropeanStockMarket(Observer):
    def update(self, *args, **kwargs):
        print("European stock market received: {0}\n{1}".format(args, kwargs))

if __name__ == "__main__":
    observable = Observable()

    american_observer = AmericanStockMarket()
    observable.register(american_observer)

    european_observer = EuropeanStockMarket()
    observable.register(european_observer)

    observable.update_observers('Market Rally', something='Hello World')

6voto

spectras Points 7058

Il existe de nombreuses façons d'"observer" quelque chose en Python. Utiliser les propriétés descripteurs , sur mesure __setattr__ , décorateurs ...

Voici un exemple simple qui utilise fonctions de première classe :

class Foo(object):
    def __init__(self):
        self.observers = []

    def register(self, fn):
        self.observers.append(fn)
        return fn   # <-- See comments below answer

    def notify_observers(self, *args, **kwargs):
        for fn in self.observers:
            fn(*args, **kwargs)

Vous pouvez ensuite enregistrer n'importe quel titre de créance.

class Bar(object):
    def do_something(self, *args, **kwargs):
        pass # do something

foo = Foo()
bar = Bar()
foo.register(bar.do_something)

Cela fonctionnera correctement. L'appel à do_something aura la bonne self valeur. Parce que les méthodes d'un objet sont des objets appelables qui portent une référence à l'instance à laquelle elles sont liées.

Cela peut aider à comprendre comment cela fonctionne sous le capot :

>>> bar
<Bar object at 0x7f3fec4a5a58>
>>> bar.do_something
<bound method Bar.do_something of <Bar object at 0x7f3fec4a5a58>>
>>> type(bar.do_something)
<class 'method'>
>>> bar.do_something.__self__
<Bar object at 0x7f3fec4a5a58>

[modifier : exemple de décorateur]

Vous pouvez également utiliser la fonction register que nous avons définie ci-dessus en tant que décorateur, comme ceci :

foo = Foo()

@foo.register
def do_something(*args, **kwargs):
    pass # do something

Pour que cela fonctionne, il suffit de se rappeler que register doit renvoyer l'appelable qu'elle a enregistré.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X