記述子は主に Python でメソッドと属性を定義するために使用されますが、その使用方法は非常に難しいものです。ここでは基本から始めて、Python で記述子記述子を使用するための簡潔なガイドをまとめます
イテレータを定義する場合、記述はオブジェクトです。反復プロトコルを実装するもの、つまり __iter__ メソッドを実装するオブジェクトです。同様に、いわゆる記述子は、記述子プロトコル、つまり __get__、__set__、および __delete__ メソッドを実装するオブジェクトです。
定義だけ見るとかなり抽象的です。口で言うだけなら簡単です。コードを見てください:
class WebFramework(object): def __init__(self, name='Flask'): self.name = name def __get__(self, instance, owner): return self.name def __set__(self, instance, value): self.name = value class PythonSite(object): webframework = WebFramework() In [1]: PythonSite.webframework Out[1]: 'Flask' In [2]: PythonSite.webframework = 'Tornado' In [3]: PythonSite.webframework Out[3]: 'Tornado'
は、記述子プロトコル __get__ と __set__ を実装するクラス WebFramework を定義します (クラスもオブジェクトであり、すべてがオブジェクトです)。 __get__ と __set__ の両方を実装することは、データ記述子と呼ばれます。 __get__ のみを実装するものは非記述子です。 2 つの違いは、インスタンスに対するディクショナリの優先順位です。
インスタンス辞書に記述子と同じ名前の属性がある場合、記述子がデータ記述子の場合はデータ記述子が最初に使用され、非データ記述子の場合は辞書内の属性が使用されます。最初に使用されます。
記述子の呼び出し
このタイプのマジックでは、呼び出しメソッドが直接使用されないことがよくあります。たとえば、デコレータは @ 記号を使用して呼び出す必要があります。イテレータは通常、反復中、または次のメソッド呼び出しを使用して使用されます。記述子は比較的単純で、オブジェクト属性が設定されるときに呼び出されます。
In [15]: webframework = WebFramework() In [16]: webframework.__get__(webframework, WebFramework) Out[16]: 'Flask'
ディスクリプタの適用
ディスクリプタの役割は主にメソッドと属性の定義です。クラスのプロパティを再記述できるため、この魔法はクラスの動作の一部を変更できます。最も単純なアプリケーションは、デコレータを使用してクラス属性のキャッシュを書き込むことです。 Flask の作者は、記述子の特性を使用してキャッシュを実装する werkzeug ネットワーク ツール ライブラリを作成しました。
class _Missing(object): def __repr__(self): return 'no value' def __reduce__(self): return '_missing' _missing = _Missing() class cached_property(object): def __init__(self, func, name=None, doc=None): self.__name__ = name or func.__name__ self.__module__ = func.__module__ self.__doc__ = doc or func.__doc__ self.func = func def __get__(self, obj, type=None): if obj is None: return self value = obj.__dict__.get(self.__name__, _missing) if value is _missing: value = self.func(obj) obj.__dict__[self.__name__] = value return value class Foo(object): @cached_property def foo(self): print 'first calculate' result = 'this is result' return result f = Foo() print f.foo # first calculate this is result print f.foo # this is result
実行結果は、最初の呼び出し中に計算された後の結果のみをキャッシュします。この利点は、ネットワーク プログラミングでは、HTTP プロトコルを解析するときに、通常、HTTP ヘッダーが Python の辞書に解析され、view 関数を使用するときにこのヘッダーが無意識のうちにアクセスされる可能性があるため、このヘッダーが記述子として使用されることです。キャッシュにより、冗長な解析を減らすことができます。
記述子は Python で広く使用されており、通常はデコレータと一緒に使用されます。偉大な魔法には大きな責任が伴います。記述子を使用して、ORM で SQL ステートメントの「プリコンパイル」を実装することもできます。記述子を適切に使用すると、Python コードをよりエレガントにすることができます。
Python で記述子記述子を使用するための簡潔なガイドの詳細な説明については、PHP 中国語 Web サイトの関連記事に注目してください。