2

次のように、インスタンスの初期化のパラメーターとして、関数に基づいてインスタンス メソッドを作成したいと思います。

from traits.api import *

class C(HasTraits):
    f = Function

c = C(f=lambda self: self)

ただし、実行すると

c.f()

それは言う(決して驚くべきことではない)

TypeError: <lambda>() takes exactly 1 argument (0 given)

f を Function から Method に変更しても、関数の引数を受け入れないため役に立ちません (instancemethod が必要です)。

私の質問は、Traits を使用するときにカスタム関数をインスタンス メソッドとして (通常のインスタンス メソッドとして self パラメータを使用して) 機能させるにはどうすればよいかということです。

4

2 に答える 2

2

次のように、新しい特性タイプ MyMethod を定義します。

import types
class MyMethod(TraitType):
    def validate(self, object, name, value): 
        if isinstance(value, types.MethodType):
            return value
        if isinstance(value, types.FunctionType):
            return types.MethodType(value, object, object.__class__)
        self.error(object, name, value)

前のコードの関数またはメソッドの代わりに使用すると、関数は自動的にインスタンスメソッドに変換されます。

于 2013-12-25T06:59:13.060 に答える
2

関数は、lambdaまたはで定義されているかどうかにかかわらdefず、メソッドではありません。

そのタイプを変更することはできません。メソッドには関数よりも多くの情報が含まれており、オブジェクトにバインドされています。selfこれが、Python が最初の ( ) パラメータに何を渡すかを知る方法です。

あなたの場合、オブジェクトにバインドされていないバインドされていないメソッドを探していますが、まだクラスにバインドされています。

通常の場合 (定義def内でメソッドをclass作成し、クラスのインスタンスを作成し、そのインスタンスでメソッドを呼び出す場合)、これは自動的に行われます。(詳細については、メソッドの仕組みを参照してください。) しかし、すべてを自分で行う場合は、バインドされたメソッドを自分で作成する必要があります。

Python の他の型と同様に、これを行うには、型をコンストラクターとして呼び出します。問題は、「バインドされたメソッド」が組み込み型としてアクセスできないことです。つまりtypes、「標準の Python インタープリターで使用されるいくつかのオブジェクト タイプの名前を定義する」モジュールに移動する必要があります。このような:

bound = types.MethodType(func, my_obj, type(my_obj))

unbound = types.UnboundMethodType(func, None, my_type)

しかし、多くの場合、これを行う正当な理由がないことに注意してください。クロージャにオブジェクトを簡単に詰め込むことができます。これらの callable はすべて同じことを行います:

func = lambda self: self
bound = types.MethodType(func, my_obj, type(my_obj))

func2 = lambda: my_obj

func3 = lambda self: self
unbound = types.UnboundMethodType(func, None, my_type)
func3a = lambda: unbound(my_obj)    

最後に 2 つの考え:

descriptors について理解していれば、@property動作させる魔法とバインドされたメソッドを動作させる魔法は互いに干渉します。それがエンソーフの特性に当てはまるかどうかはわかりませんが、そうかもしれません。したがって、あなたの質問に対する答えは、「それはできません」となる可能性があります。代わりに、Function特性を作成してから、その特性を明示的に呼び出すラッパー メソッドを作成する必要があります。

Python 2.x の代わりに 3.x を使用すると、バインドされていないメソッドがなくなります (クラスは単純な古い関数を使用するだけです)。

于 2013-12-24T21:07:28.030 に答える