2

クラスプロパティをプロパティメソッドで条件付きでオーバーライドすることは可能ですか?

dictを渡すことでインスタンス化できるこのクラスがある場合:

def Foo(Object):
    def __init__(self, **kwargs):
        self.__dict__.update(kwargs)

    # pseudo code (this doesn't work)
    if not self.bar:
        @property
        def bar(self):
            return u"I have overridden foo's bar"

そして、私はこのインスタンスを作成し、またはに設定しbarます:''None

my_foo = Foo(**{'bar':u''})

bar次に、プロパティを呼び出します。

my_foo.bar

取得します

u"I have overridden foo's bar"

オブジェクトの作成時に渡された値ではbarなく、プロパティメソッドを返したいのですが。bar

どういうわけかそれはできますか?どんな助けでも素晴らしいでしょう。

4

2 に答える 2

0

Pythonのプロパティは上書きできません。上書きすると、が発生しAttributeErrorます。ただし、オーバーライド値を保存してから、プロパティの実行時にそれらを検索することもできます。

def overridable(of):
    def nf(self):
        if hasattr(self, "_overrides") and of.__name__ in self._overrides:
            return self._overrides[of.__name__]
        return of(self)
    return nf


class Foo(object):
    _overrides = {}

    def __init__(self, **kwargs):
        for k, v in kwargs.iteritems():
            try:
                setattr(self, k, v)
            except AttributeError:
                self._overrides[k] = v

    @property
    @overridable
    def bar(self):
        return u'I have overridden foo\'s bar'


my_foo = Foo(bar=3)
print my_foo.bar
于 2012-10-08T02:44:08.223 に答える
0

プロパティをオーバーライドするには、インスタンスではなくクラスに作用する必要があります。これは、インスタンス上のそれらの機構が__dict__ルックアップの前に呼び出され、最終的にAttributeErrorsになるためです。代わりに、クラスに別のプロパティを設定できます。

ただし、これを行うには、インスタンスを作成するたびにクラスを変更するか(これは望ましくないと思います)、新しいクラスを動的に生成する必要があります。

例えば:

class Foo(object):
    def __init__(self, val):
        self._val = val
    @property
    def val(self):
        return self._val

class SubType(Foo):
    def __new__(cls, val):
        if val % 2:
            #random condition to change the property
            subtype = type('SubFoo', (SubType,),
                           {'val': property((lambda self: self._val + 1))})
                return object.__new__(subtype)
            else:
                return object.__new__(cls)

そして結果は次のとおりです。

>>> d = SubType(3)  #property changed
>>> d.val
4
>>> f = SubType(2)  #same property as super class
>>> f.val
2

私はこの種のハックはあまり好きではありません。おそらく、物事を行うためのより簡単な方法は、プロパティ値を計算するプライベートメソッドを呼び出すことです。次に例を示します。

class Foo(object):
    def __init__(self, val):
        self._val = val
    def _compute_val(self):
        return self._val
    @property
    def val(self):
        return self._compute_val()

class SubFoo(Foo):
    def _compute_val(self):
        if self._val % 2:
                return self._val + 1
        else:
                return self._val

これにより、以前と同じ結果が得られます。

>>> d = SubFoo(3)
>>> d.val
4
>>> f = SubFoo(2)
>>> f.val
2

このトリックは、プロパティに適用されますが、テンプレートメソッドデザインパターンの適用と見なすことができると思います。

于 2012-10-09T05:55:39.113 に答える