質問

サブクラスで上書きする(getメソッド)プロパティを持つ基本クラスがあります。私の最初の考えは次のようなものでした:

class Foo(object):
    def _get_age(self):
        return 11

    age = property(_get_age)


class Bar(Foo):
    def _get_age(self):
        return 44

これは機能しません(サブクラスbar.ageは11を返します)。ラムダ式が機能するソリューションを見つけました:

age = property(lambda self: self._get_age())

それで、これはプロパティを使用してサブクラスでそれらを上書きするための適切なソリューションですか、またはこれを行う他の好ましい方法がありますか?

役に立ちましたか?

解決

クラスメソッドをオーバーライドするときに @classmethod デコレータを繰り返すのと同様に、単に property()を繰り返すことを好みます。

これは非常に冗長に思えますが、少なくともPythonの標準では、気付くでしょう:

1)読み取り専用プロパティの場合、 property をデコレータとして使用できます:

class Foo(object):
    @property
    def age(self):
        return 11

class Bar(Foo):
    @property
    def age(self):
        return 44

2)Python 2.6では、プロパティはメソッドのペアを成長させました setter および deleter を使用して、読み取り専用プロパティで既に使用可能なショートカットを一般的なプロパティに適用できます。

class C(object):
    @property
    def x(self):
        return self._x

    @x.setter
    def x(self, value):
        self._x = value

他のヒント

選択した回答が、プロパティメソッドのオーバーライドを可能にする理想的な方法であることに同意しません。ゲッターとセッターがオーバーライドされると予想される場合は、lambdaを使用してselfへのアクセスを提供し、 lambda self:self。< property func> のようなものを使用できます。

これは(少なくとも)Pythonバージョン2.4から3.6で機能します。

直接property()呼び出しとしてではなく、デコレータとしてpropertyを使用してこれを行う方法を知っている人がいれば、それを聞きたいです!

例:

class Foo(object):
    def _get_meow(self):
        return self._meow + ' from a Foo'
    def _set_meow(self, value):
        self._meow = value
    meow = property(fget=lambda self: self._get_meow(),
                    fset=lambda self, value: self._set_meow(value))

これにより、オーバーライドを簡単に実行できます:

class Bar(Foo):
    def _get_meow(self):
        return super(Bar, self)._get_meow() + ', altered by a Bar'

そのため:

>>> foo = Foo()
>>> bar = Bar()
>>> foo.meow, bar.meow = "meow", "meow"
>>> foo.meow
"meow from a Foo"
>>> bar.meow
"meow from a Foo, altered by a Bar"

遊びのオタク

追加のクラスを作成せずに行う別の方法。 2つのうち1つだけをオーバーライドする場合に何をするかを示すために、setメソッドを追加しました。

class Foo(object):
    def _get_age(self):
        return 11

    def _set_age(self, age):
        self._age = age

    age = property(_get_age, _set_age)


class Bar(Foo):
    def _get_age(self):
        return 44

    age = property(_get_age, Foo._set_age)

これはかなり不自然な例ですが、アイデアを得る必要があります。

はい、これがその方法です。プロパティ宣言は、親クラスの定義が実行されるときに実行されます。つまり、「見る」ことしかできないということです。親クラスに存在するメソッドのバージョン。そのため、子クラスでこれらのメソッドの1つ以上を再定義するときは、子クラスのバージョンのメソッドを使用してプロパティを再宣言する必要があります。

私はあなたの解決策に同意します。これはオンザフライのテンプレート方法のようです。 この記事はあなたの問題を扱っており、まさにあなたの解決策を提供します。

このようなものは動作します

class HackedProperty(object):
    def __init__(self, f):
        self.f = f
    def __get__(self, inst, owner):    
        return getattr(inst, self.f.__name__)()

class Foo(object):
    def _get_age(self):
        return 11
    age = HackedProperty(_get_age)

class Bar(Foo):
    def _get_age(self):
        return 44

print Bar().age
print Foo().age

@ mr-b と同じですが、デコレータがあります。

class Foo(object):
    def _get_meow(self):
        return self._meow + ' from a Foo'
    def _set_meow(self, value):
        self._meow = value
    @property
    def meow(self):
        return self._get_meow()
    @meow.setter
    def meow(self, value):
        self._set_meow(value)

これにより、オーバーライドを簡単に実行できます:

class Bar(Foo):
    def _get_meow(self):
        return super(Bar, self)._get_meow() + ', altered by a Bar'

子クラスから親クラスにプロパティを設定する際に問題が発生しました。次の回避策は、親のプロパティを拡張しますが、親の_set_ageメソッドを直接呼び出して拡張します。しわは常に正しいはずです。それは少しjavathonicです。

import threading


class Foo(object):
    def __init__(self):
        self._age = 0

    def _get_age(self):
        return self._age

    def _set_age(self, age):
        self._age = age

    age = property(_get_age, _set_age)


class ThreadsafeFoo(Foo):

    def __init__(self):
        super(ThreadsafeFoo, self).__init__()
        self.__lock = threading.Lock()
        self.wrinkled = False

    def _get_age(self):
        with self.__lock:
             return super(ThreadsafeFoo, self).age

    def _set_age(self, value):
        with self.__lock:
            self.wrinkled = True if value > 40 else False
            super(ThreadsafeFoo, self)._set_age(value)

    age = property(_get_age, _set_age)
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top