3

アルゴリズムを実装するスーパークラスにグラフィック機能を追加するサブクラスがあります。したがって、いくつかの追加の初期化関数に加えて、このサブクラスは、スーパークラスの各アルゴリズム計算関数の実行後にグラフィックを更新するだけで済みます。

クラス:

class graph(algorithms):
  ... #initialization and refresh decorators

  @refreshgraph
  def algorithm1(self, *args, **kwargs):
    return algorithms.algorithm1(self, *args, **kwargs)

  @refreshgraph
  def algorithm2(self, *args, **kwargs):
    return algorithms.algorithm2(self, *args, **kwargs)

  ... #and so on

スーパークラスで定義されたすべての非プライベート メソッドを自動的に装飾する Pythonic の方法はありますか?新しいアルゴリズムを追加した場合、サブクラスで明示的に言及する必要はありませんか? また、スーパークラスのメソッドの一部を明示的に除外できるようにしたいと考えています。

4

2 に答える 2

3

デフォルトでは、サブクラスは常に親クラスからすべてのメソッドを取得します。他の言語がプライバシーのために使用する動作 (たとえば、C# の 'private' または 'protected' 修飾子) をエミュレートしたい場合は、2 つのオプションがあります。

1) Python の規則 (これは単なる規則です) では、名前の先頭にアンダースコアが 1 つあるメソッドは、定義クラスの外部からアクセスするように設計されていません。

2) 先頭にアンダースコアが 2 つある名前、バイトコード内でマングルされるため、他のコードからは独自の名前では見えません。ParentClass.__private は ParentClass 内で可視ですが、ParentClass._ParentClass__private として ParentClass の外部からのみアクセスできます。(素晴らしい説明はこちら)。Python には真にプライベートなものはありません ;)

継承されたメソッドをオーバーライドするには、派生クラスで同じ名前を定義するだけです。派生クラス内で親クラスのメソッドを呼び出すには、例で行ったように、またはsuperを使用して実行できます。

def algorithm2(self, *args, **kwargs):
  super(graph, self).algorithm2(self, *args, **kwargs)
  # do other derived stuff here....
  self.refresh()
于 2013-09-12T01:47:14.633 に答える
0

これは醜いですが、私はそれがあなたが望むことをすると思いますが、継承はありません:

class DoAfter(object):
    def __init__(self, obj, func):
        self.obj = obj
        self.func = func

    def __getattribute__(self, attr, *a, **kw):      
        obj = object.__getattribute__(self, 'obj')

        if attr in dir(obj):
            x = getattr(obj, attr)

            if callable(x):
                def b(*a, **kw):
                    retval = x(*a, **kw)
                    self.func()
                    return retval
                return b
            else:
                return x

        else:
            return object.__getattribute__(self, attr)

次のように使用します。

>>> class A(object):
...     def __init__(self):
...         self.a = 1
... 
...     def boo(self, c):
...         self.a += c
...         return self.a
>>> def do_something():
...     print 'a'
>>> a = A()
>>> print a.boo(1)
2
>>> print a.boo(2)
4
>>> b = DoAfter(a, do_something)
>>> print b.boo(1)
a
5
>>> print b.boo(2)
a
7

AA.booが呼び出されるたびにカウンターをインクリメントします。DoAfter は A をラップするため、インスタンス内の任意のメソッドをaのメンバーであるかのように呼び出すことができますbすべてのメソッドがこのようにラップされているためdo_something()、メソッドがアクセスされるたびに呼び出されることに注意してください。

これはほとんどテストされておらず、推奨されておらず、おそらく悪い考えです。しかし、私はそれがあなたが求めたものをしていると思います。

編集:継承でこれを行うには:

class graph(algorithms):
    def refreshgraph(self):
        print 'refreshgraph'

    def __getattribute__(self, attr):
        if attr in dir(algorithms):
            x = algorithms.__getattribute__(self, attr)

            if callable(x):
                def wrapped(*a, **kw):
                    retval = x(*a, **kw)
                    self.refreshgraph()
                    return retval
                return wrapped
            else:
                return x

        else:
            return object.__getattribute__(self, attr)
于 2013-09-12T02:34:11.617 に答える