4

execute問題:別のメソッドを呼び出すテンプレート メソッドを含むクラスがあります_execute。サブクラスは_execute、特定の機能を実装するために上書きすることになっています。この機能は、 の docstring で文書化する必要があります_execute。上級ユーザーは、独自のサブクラスを作成してライブラリを拡張できます。ただし、そのようなサブクラスを扱う別のユーザーは のみを使用する必要があるexecuteため、 を使用しても正しい docstring が表示されませんhelp(execute)

executeしたがって、サブクラスで の docstring が の docstring に自動的に置き換えられるように、基本クラスを変更するとよいでしょう_execute。これを行う方法はありますか?

これをユーザーに完全に透過的にするために、これを行うためのメタクラスを考えていました。

4

5 に答える 5

4

サブクラスに元のメソッドをコピーしても構わない場合は、次の手法を使用できます。

import new

def copyfunc(func):
    return new.function(func.func_code, func.func_globals, func.func_name,
                        func.func_defaults, func.func_closure)

class Metaclass(type):
    def __new__(meta, name, bases, attrs):
        for key in attrs.keys():
            if key[0] == '_':
                skey = key[1:]
                for base in bases:
                    original = getattr(base, skey, None)
                    if original is not None:
                        copy = copyfunc(original)
                        copy.__doc__ = attrs[key].__doc__
                        attrs[skey] = copy
                        break
        return type.__new__(meta, name, bases, attrs)

class Class(object):
    __metaclass__ = Metaclass
    def execute(self):
        '''original doc-string'''
        return self._execute()

class Subclass(Class):
    def _execute(self):
        '''sub-class doc-string'''
        pass
于 2008-09-16T14:02:38.390 に答える
2

execute基本クラスの関数を直接オーバーライドできない理由はありますか?

class Base(object):
    def execute(self):
        ...

class Derived(Base):
    def execute(self):
        """Docstring for derived class"""
        Base.execute(self)
        ...stuff specific to Derived...

上記を行いたくない場合:

メソッド オブジェクトは属性への書き込みをサポートしていないため、実際の関数オブジェクト__doc__を変更する必要があります。__doc__基本クラスのものをオーバーライドしたくないので、各サブクラスに独自のコピーを与える必要がありますexecute:

class Derived(Base):
    def execute(self):
        return Base.execute(self)

    class _execute(self):
        """Docstring for subclass"""
        ...

    execute.__doc__= _execute.__doc__

しかし、これは再定義の回り道に似ていexecuteます...

于 2008-09-16T13:31:44.953 に答える
1

functools.wraps() デコレーターを見てください。これはすべて実行されますが、適切なコンテキストで実行できるかどうかはわかりません

于 2008-09-16T15:19:05.897 に答える
0

これにアプローチする最も簡単で最もPython的な方法は、サブクラスでexecuteを再定義し、基本クラスのexecuteメソッドを呼び出すことであることに同意します。

class Sub(Base):
    def execute(self):
        """New docstring goes here"""
        return Base.execute(self)

これは、目的を達成するための非常に小さなコードです。唯一の欠点は、Base を拡張するすべてのサブクラスでこのコードを繰り返さなければならないことです。ただし、これは、必要な動作に対して支払う小さな代償です。

実行のためのdocstringが動的に生成されることを確認するずさんで冗長な方法が必要な場合は、記述子プロトコルを使用できます。これは、ここでの他の提案よりもコードが大幅に少なくなります。既存の関数に記述子を設定することはできないため、これは面倒です。つまり、execute は、__call__メソッドを使用して別のクラスとして作成する必要があります。

これを行うコードは次のとおりですが、上記の例ははるかに単純で Pythonic であることに注意してください。

class Executor(object):
    __doc__ = property(lambda self: self.inst._execute.__doc__)

    def __call__(self):
        return self.inst._execute()

class Base(object):
    execute = Executor()

class Sub(Base):
    def __init__(self):
        self.execute.inst = self

    def _execute(self):
        """Actually does something!"""
        return "Hello World!"

spam = Sub()
print spam.execute.__doc__  # prints "Actually does something!"
help(spam)                  # the execute method says "Actually does something!"
于 2008-09-16T14:17:43.780 に答える
0

ドキュメント文字列は保存されているので、事後__doc__にドキュメント文字列に基づいて再割り当てするのはそれほど難しくありません_execute

基本的:

class MyClass(object):
    def execute(self):
        '''original doc-string'''
        self._execute()

class SubClass(MyClass):
    def _execute(self):
        '''sub-class doc-string'''
        pass

    # re-assign doc-string of execute
    def execute(self,*args,**kw):
        return MyClass.execute(*args,**kw)
    execute.__doc__=_execute.__doc__

SubClassexecute は、ドキュメント文字列が for ではなく forの execute のバージョンにアタッチされるように再宣言する必要がありますMyClass(そうしないと、他のサブクラスに干渉します)。

これは非常に整然とした方法ではありませんが、ライブラリのユーザーの視点からは、望ましい結果が得られるはずです。これをメタクラスにまとめて、サブクラス化を容易にすることができます。

于 2008-09-16T13:25:12.177 に答える