1

クラスのオブジェクトが作成された「モード」に依存する f メソッドを持つクラスを作成したいと思います。

以下のコードは機能しませんが、私がやろうとしていることを理解していただければ幸いです。私の考えは、各モードの設定を定義する辞書を用意することです (この場合、関数またはメソッドを self.f に割り当てるため、init 関数で多くの if elif ステートメントを使用するのではなく、正しい値を割り当てるだけです)。辞書を使って。

class A(object):
    _methods_dict={
            'a':A.f1,
            'b':A.f2
            }    

    def __init__(self,mode = 'a'):
        self.f = _methods_dict[mode]


    def f1(self,x):
        return x

    def f2(self,x):
        return x**2

なぜこれが機能しないのか理解できません。どうすれば修正できますか? また、同じ種類の機能を取得するためのより良い (そしてより Pythonic な) アプローチはありますか?

4

3 に答える 3

4

2 つの関数の名前getattr()を保存してから、バインドされたメソッドを取得するために使用します__init__

class A(object):
    _methods_dict = {
        'a': 'f1',
        'b': 'f2'
    }    

    def __init__(self, mode='a'):
        self.f = getattr(self, self._methods_dict[mode])

    def f1(self, x):
        return x

    def f2(self, x):
        return x ** 2

または、メソッドをプロキシするだけです:

class A(object):
    _methods_dict = {
        'a': 'f1',
        'b': 'f2'
    }

    def __init__(self,mode = 'a'):
        self._mode = mode

    @property
    def f(self):
        return getattr(self, self._methods_dict[self._mode])

    def f1(self, x):
        return x

    def f2(self, x):
        return x ** 2

このfプロパティは、現在のモードの正しいバインド メソッドを返すだけです。プロパティを使用すると、呼び出し署名の処理が簡素化され、必要に応じてユーザーがイントロスペクトするための実際のメソッドが提供されます。

どちらの方法でも最終結果は同じです。

>>> a1 = A()
>>> a2 = A('b')
>>> a1.f(10)
10
>>> a2.f(10)
100

違いはインスタンスに格納されるものにあり、最初のメソッドはバインドされたメソッドを格納します。

>>> vars(a1)
{'f': <bound method A.f1 of <__main__.A object at 0x10aa1ec50>>}
>>> vars(a2)
{'f': <bound method A.f2 of <__main__.A object at 0x10aa1ed50>>}

対他の方法:

>>> vars(a1)
{'_mode': 'a'}
>>> vars(a2)
{'_mode': 'b'}

大した違いはないように思えるかもしれませんが、後者の方法では、問題なくピクルおよびディープ コピーできるインスタンスが作成されます。

于 2013-04-11T08:45:05.567 に答える
0

2 つの別個のクラスを作成できます。

class Base(object):
    # place here all attributes shared in common among the Modes
    pass

class ModeA(Base):
    def f(self, x):
        return x

class ModeB(Base):
    def f(self, x):
        return x**2

def make_mode(mode, *args, **kwargs):
    mode_dict = {'a':ModeA, 'b':ModeB}
    return mode_dict[mode](*args, **kwargs)

a = make_mode('a')
print(a.f(10))
# 10

b = make_mode('b')
print(b.f(10))
# 100
于 2013-04-11T09:07:18.450 に答える
0

最初の質問 (「これが機能しない理由」) に答えるには: クラス オブジェクト "A" は、クラス ステートメント全体 (はい、"class" は実行可能なステートメントです) ブロックの後にのみ作成され、モジュール名 "A" にバインドされます。は終了しているため、このブロック内では名前もクラス オブジェクト自体も参照できません。

于 2013-04-11T09:20:19.683 に答える