ホームページ  >  記事  >  バックエンド開発  >  Python で記述子記述子を使用するための簡潔なガイドの詳細な説明

Python で記述子記述子を使用するための簡潔なガイドの詳細な説明

高洛峰
高洛峰オリジナル
2017-03-03 15:53:381374ブラウズ

記述子は主に 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 サイトの関連記事に注目してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。