5

私はこのようなことをしたいです:

class SillyWalk(object):
    @staticmethod
    def is_silly_enough(walk):
        return (False, "It's never silly enough")
    def walk(self, appraisal_method=is_silly_enough):
        self.do_stuff()
        (was_good_enough, reason) = appraisal_method(self)
        if not was_good_enough:
            self.execute_self_modifying_code(reason)
        return appraisal_method
    def do_stuff(self):
        pass
    def execute_self_modifying_code(self, problem):
        from __future__ import deepjuju
        deepjuju.kiss_booboo_better(self, problem)

誰かができるという考えで

>>> silly_walk = SillyWalk()
>>> appraise = walk()
>>> is_good_walk = appraise(silly_walk)

また、魔法の機械学習を行うこともできます。この最後のビットは私にとって特に興味深いものではありません。これは、関数内のコンテキストと呼び出し元の観点の両方で静的メソッドの使用を例示する方法として私が最初に思いついたものです。

とにかく、これは実際には関数ではないため、機能しません。これは、メソッドが元の関数を返すis_silly_enoughオブジェクトです。これは、オブジェクト属性として参照されている場合にのみ「通常の」方法で機能することを意味します。問題のオブジェクトは、デコレータがの属性とその名前で最初に定義された関数の間に配置する関数によって作成されます。__get__is_silly_enoughstaticmethod()SillyWalkis_silly_enough

これは、いずれかまたはその呼び出し元appraisal_method内からのデフォルト値を使用するには、次のいずれかを行う必要があることを意味します。 SillyWalk.walk

  • ただ呼び出すappraisal_method.__get__(instance, owner)(...)のではなく呼び出すappraisal_method(...)
  • または、それをオブジェクトの属性として割り当ててから、そのオブジェクトプロパティを、呼び出すのと同じように呼び出すメソッドとして参照しますappraisal_method

これらのソリューションのどちらも特にPythonic™のようには見えないので、この種の機能を取得するためのより良い方法があるのではないかと思います。基本的に、メソッドがデフォルトで特定のクラスまたは同じクラスのスコープ内で定義された静的メソッドを使用して、その日課の一部を実行するように指定する方法が必要です。

その特定の関数を呼び出さないようにするというメッセージを伝えNoneたいので、は使用しない方がいいです。またはNoneのような他の値を使用できると思いますが、a)厄介なb)表現できるように見える何かのために、余分な数行のコードや、それ以外の場合は冗長なドキュメントを作成する必要があるのは面倒なようですデフォルトパラメータとして非常に簡潔に。FalseNotImplemented

これを行うための最良の方法は何ですか?

4

3 に答える 3

2

たぶん、必要なのは、そもそも関数(メソッドではなく)を使用することだけですか?

class SillyWalk(object):
    def is_silly_enough(walk):
        return (False, "It's never silly enough")

    def walk(self, appraisal_function=is_silly_enough):
        self.do_stuff()
        (was_good_enough, reason) = appraisal_function(self)
        if not was_good_enough:
            self.execute_self_modifying_code(reason)
        return appraisal_function
    def do_stuff(self):
        pass
    def execute_self_modifying_code(self, problem):
        deepjuju.kiss_booboo_better(self, problem)

クラスが作成されると(コードの最後で)is_silly_enoughがクラスメソッドとしてバインドされる場合でも、appraisal_functionのデフォルトはメソッドではなく関数になることに注意してください。

この意味は

>>> SillyWalk.is_silly_enough
<unbound method SillyWalk.is_silly_enough>

しかし

>>> SillyWalk.walk.im_func.func_defaults[0] # the default argument to .walk
<function is_silly_enough at 0x0000000002212048>

また、walk引数を使用してis_silly_enoughを呼び出すか、.is_silly_enough()を使用してwalkインスタンスを呼び出すことができます。

is_silly_enoughを静的メソッドにしたい場合は、いつでも追加できます

    is_silly_enough = staticmethod(is_silly_enough)

散歩の定義の後のどこでも。

于 2010-06-21T12:13:45.037 に答える
2

関数定義ヘッダー内で使用する(非)ラッパー関数を作成することになりました。

def walk(self, appraisal_method=unstaticmethod(is_silly_enough)):

これは実際には機能しているように見えますが、少なくとも、パスせずにドキュメントテストが失敗するようになります。

ここにあります:

def unstaticmethod(static):
    """Retrieve the original function from a `staticmethod` object.

    This is intended for use in binding class method default values
      to static methods of the same class.

    For example:
        >>> class C(object):
        ...     @staticmethod
        ...     def s(*args, **kwargs):
        ...         return (args, kwargs)
        ...     def m(self, args=[], kwargs={}, f=unstaticmethod(s)):
        ...         return f(*args, **kwargs)
        >>> o = C()
        >>> o.s(1, 2, 3)
        ((1, 2, 3), {})
        >>> o.m((1, 2, 3))
        ((1, 2, 3), {})
    """
    # TODO: Technically we should be passing the actual class of the owner
    #         instead of `object`, but
    #         I don't know if there's a way to get that info dynamically,
    #         since the class is not actually declared
    #         when this function is called during class method definition.
    #       I need to figure out if passing `object` instead
    #         is going to be an issue.
    return static.__get__(None, object)

アップデート:

unstaticmethod関数自体のdoctestを作成しました。彼らも合格します。これが実際に賢明なことであるかどうかはまだ完全にはわかりませんが、うまくいくようです。

于 2010-06-21T11:20:46.877 に答える
1

あなたが求めているものを正確に取得できるかどうかはわかりませんが、getattr を使用する方がクリーンでしょうか?

>>> class SillyWalk(object):
    @staticmethod
    def ise(walk):
        return (False, "boo")
    def walk(self, am="ise"):
        wge, r = getattr(self, am)(self)
        print wge, r


>>> sw = SillyWalk()
>>> sw.walk("ise")
False boo
于 2010-06-21T10:21:43.517 に答える