ホームページ >バックエンド開発 >Python チュートリアル >Python 黒魔術 @propertydecorator の使用スキルの分析
@property の用途は何ですか? 表面的には、メソッドに属性としてアクセスすることです
class Circle(object): def __init__(self, radius): self.radius = radius @property def area(self): return 3.14 * self.radius ** 2 c = Circle(4) print c.radius print c.areaエリアがメソッド形式として定義されていることがわかります。 @property を追加すると、プロパティとして c.area に直接アクセスできるようになります。
ここで問題が発生します (どの掘削機テクノロジーが優れているかということではありません)。 c.area が呼び出されるたびに、計算が 1 回行われます。 CPU の無駄、一度だけ計算する方法は? @lazy のメカニズムの説明。
ここで、lazy クラスには、それが記述子であることを示す __get__ メソッドがあり、順序の問題により、最初に c.__dict__ が検索されます。見つからない場合は、クラス空間に移動して検索します。Circle クラスには area() メソッドがあるため、__get__ でインスタンスの area() メソッドを呼び出して動的に結果を計算します。同じ名前の属性をインスタンスに追加し、結果をそれに割り当てます。つまり、c.__dict__ に追加されます。
class lazy(object): def __init__(self, func): self.func = func def __get__(self, instance, cls): val = self.func(instance) setattr(instance, self.func.__name__, val) return val class Circle(object): def __init__(self, radius): self.radius = radius @lazy def area(self): print 'evalute' return 3.14 * self.radius ** 2 c = Circle(4) print c.radius print c.area print c.area print c.area
コード 1 と 2 の違いは
class Parrot(object): def __init__(self): self._voltage = 100000 @property def voltage(self): """Get the current voltage.""" return self._voltage if __name__ == "__main__": # instance p = Parrot() # similarly invoke "getter" via @property print p.voltage # update, similarly invoke "setter" p.voltage = 12
python2.6 では、テストを個別に実行します
フラグメント 1: 予想されるエラー メッセージ AttributeError: can't set Attribute が表示されますプロンプトが表示されます
python2.6 ドキュメントを参照してください。@property は、対応する @voltage.setter を提供しません。これは当然のことです。 Python2.6 ドキュメントでは、次の情報を見つけることができます:
BIF:
property([fget [, fset[, fdel[, doc]]]])new のプロパティ属性を返す-style クラス (オブジェクトから派生するクラス)
Python2.6 では、クラスを定義するときに明確な説明がない場合、組み込み型オブジェクトがデフォルトの基本クラスではないことがわかります (コード スニペット 2)。私たちが定義する Parrot (コード スニペット 2) はオブジェクトを継承しません
そして、オブジェクト クラスは必要な @property 関数を提供するだけです。次の情報が見つかりました:
新しいスタイル クラス
継承する任意のクラス。これには、list や dict などのすべての組み込み型が含まれます。__slots__、記述子、プロパティ、__getattribute__() などの Python の新しい多機能機能を使用できるのは、新しいスタイルのクラスのみです。同時に、検証することもできます。Python 2.6 コード
class Parrot: def __init__(self): self._voltage = 100000 @property def voltage(self): """Get the current voltage.""" return self._voltage if __name__ == "__main__": # instance p = Parrot() # similarly invoke "getter" via @property print p.voltage # update, similarly invoke "setter" p.voltage = 12
Python 2.6 コード
class Parrot(object):
返された 0de78ee0d3b407c99059b714f3837c5b であることがわかります。 '> は必要なオブジェクト タイプです (Python 3.0 はオブジェクト クラスをデフォルトの基本クラスとして使用するため、すべては f5ae6bbdf402bfea04a71faa8c02de77 を返します)
Python版のコードでは、クラスファイルを定義する際に、オブジェクトを明示的に定義するのが良い習慣だと思います
最終的なコードは以下のようになります:
class A: pass >>type(A) <type 'classobj'>
さらに、 @property を追加しました2.6と3.0、2.5にはこの機能はありません。
Python のブラック マジック @プロパティ デコレータのヒントや関連記事をさらに詳しく知りたい場合は、PHP 中国語 Web サイトに注目してください。