7

Java のように Python でオブザーバー/オブザーバブル機能を備えたプログラムを作成するにはどうすればよいですか? Javaで次のようなものを書きます。

import java.util.Observable;
import java.util.Observer;


public class ObservDemo extends Object {
  MyView view;
  MyModel model;

  public ObservDemo() {

    view = new MyView();
    model = new MyModel();
    model.addObserver(view);

  }

  public static void main(String[] av) {
    ObservDemo me = new ObservDemo();
    me.demo();
  }

  public void demo() {
    model.changeSomething();
  }

  /** The Observer normally maintains a view on the data */
  class MyView implements Observer {
    /** For now, we just print the fact that we got notified. */
    public void update(Observable obs, Object x) {
      System.out.println("update(" + obs + "," + x + ");");
    }
  }

  /** The Observable normally maintains the data */
  class MyModel extends Observable {
    public void changeSomething() {
      // Notify observers of change
      setChanged();
      notifyObservers();
    }
  }
}

(このコードは次のリンクから取得され ます http://www.java2s.com/Code/Java/Design-Pattern/AsimpledemoofObservableandObserver.htm )

Pythonでそのようなことを達成するにはどうすればよいですか?

4

1 に答える 1

8

まず第一に、Martijn Pietersが言ったように、PythonはJavaではありません。これは、おそらくオブザーバー/観察されたパターン全体は必要ないが、より単純化されたバージョンに要約できることを意味します。最後に、もう少しpythonesqueなものを示しますが、非常に基本的なJava実装にとどまるために、次のようなものを試すことができます。

class Observer(object):
    def notify(self,*args,**kwargs):
        print args,kwargs

class Target(object):
    def __init__(self,*observers):
        self.observes = observers

    #this notify for every access to the function
    def event(self,data):
        for obs in self.observes:
            obs.notify('event',data)
        print "event with",data

t = Target(Observer())
t.event(1)
#('event', 1) {}
#event with 1

それ以外の場合は、デコレータを使用して実装できます。これは非常によく似ています。

def observe(f):
    def decorated(self,*args,**kwargs):
        for obs in self.observes:
            obs.notify('event',*args,**kwargs)
        return f(self,*args,**kwargs)
    return decorated

class Target(object):
    def __init__(self,*observers):
        self.observes = observers

    @observe
    def otherevent(self,data):
        print "other event with",data

現在、これらのメソッドはすべて機能しますが、あまりPython的ではありません。このようなものをpythonicの方法で実装するために頭に浮かぶ最良の方法は、属性アクセスをチェックしてコールバック関数を呼び出すラッパーを実装することです(これはオブザーバーの通知関数ですが、より一般的なアプローチです)

class Wrapper(object):
    def __init__(self,wrapped,*callbacks):
        self.wrapped = wrapped
        self.callbacks = callbacks

    def __getattr__(self,name):
        res = self.wrapped.__getattribute__(name)
        if not callable(res):
            return res
        def wrap(*args,**kwargs):
            for c in self.callbacks:
                c(self.wrapped,f,*args,**kwargs)
            return res(*args,**kwargs)
        return wrap

    def __str__(self):
        return self.wrapped.__str__()

#in this example I will keep a record of each call performed on a list
called = []
#this is the list
a = []
#and this is the wrapped list
w = Wrapper(a,lambda f,v,ign: called.append((f,v)) )
#I append an element to the wrapper
w.append(1)
#and I can see that it modify the original list
print a
#the print of the wrapped is well behaved, having defined the __str__ function
print w
#and we can see which function we called and which were the parameters
print called

このアプローチは、すべての魔法のメソッドを手動でリダイレクトする必要があるため、もう少し複雑ですが、ジェネリックを指定する必要なしに、オブザーバーパターンを任意の種類のオブジェクトに実装し、互換性のある関数をアタッチできるため、はるかに強力ですオブザーブのクラス。すべての魔法の関数呼び出しを自動的にリダイレクトする方法はありますが、それは少し複雑で、要点を混乱させるだけです

Pythonで作業するときにJavaを忘れるのが最も早いほど、Javaはより楽しくなります。この記事を読むことをお勧めします:

http://dirtsimple.org/2004/12/python-is-not-java.html

あなたの仕事で頑張ってください!

于 2012-11-23T12:00:19.253 に答える