ホームページ  >  記事  >  バックエンド開発  >  Descriptorを使用してPythonでクラスレベルの属性(プロパティ)を実装する方法の詳細な説明

Descriptorを使用してPythonでクラスレベルの属性(プロパティ)を実装する方法の詳細な説明

WBOY
WBOYオリジナル
2016-06-16 08:42:01844ブラウズ

前の記事では、Python の記述子の概念と使用法を簡単に紹介しましたが、興味のある学生はすでにこのスキルを習得しているかもしれません。この記事では、状況を理解していない学生がより簡単に理解できるように、ディスクリプタの使用シナリオを通じてケースをもう一度示します。

まずデコレーターについて話しましょう

これら 2 つの単語は確かに似ており、使用上は切り離すことができません。これにより、デコレータとディスクリプタが正確に何なのか、なぜ @ 記号とディスクリプタを使用する必要があるのか​​を理解することが難しくなります。

この 2 つを組み合わせた記事も多く、読んだ後混乱を感じました。実際、ナレッジ ポイントを学習することは、機能を開発するプロジェクトに取り組むことと同じです。関数を分割するときは、開発者にタスクを割り当てる前に、タスクを十分小さなサイズに分割するよう最善を尽くします。これにより、各タスクの独立性と整合性が確保され、進捗管理が容易になります。タスクを開発するとき、関数間の高度な結合を避けるためにすべてのタスクを関数/インターフェイスに入れることはできません。これにより、後のメンテナンスが困難になります。

1 つの技術点の学習に戻りましょう。常に 2 つ以上の技術点を同時に習得しようとすると、長時間作業しても混乱する結果になる可能性があります。

くそー、やりすぎのようだ。

ディスクリプタはディスクリプタ、デコレータはデコレータと言われます。わからないことがあったら、一つずつ分解してください。それでは、最初に Decorator について話しましょう。重要な点は、これが糖衣構文であることを理解する必要があるということです。いわゆる糖衣構文を使用すると、簡単な方法でコードを作成できます。基本的に、デコレータは次のようなものです:

コードをコピー コードは次のとおりです:

def デコレータ(関数):
Def ラッパー():
print 'デコレータ内'
func()
リターンラッパー

def func():
'関数内' を印刷

# 機能を飾ります
func =decorator(func) # 左側の func は実際にはラッパーであり、実行すると func() が実行されます
。 # func を定義するときに @
を追加するのと同等 @デコレータ
def func():
'関数内' を印刷

メイントピック: 記述子を使用してクラスレベルのプロパティを作成する

共通のプロパティは次のとおりです:

コードをコピー コードは次のとおりです:

クラス Foo(オブジェクト):
_name = 'the5fire'

@プロパティ
定義名(自分):
return self._name

ここでのプロパティの使用はインスタンスレベルのアプリケーションです。 foo.name は foo = Foo() の後にのみ可能であるためです。

しかし、クラスレベルの属性が必要な場合はどうすればよいでしょうか? クラスメソッドと同様に、クラスをインスタンス化せずに呼び出すことができます。対応する要件は次のとおりで、基本クラス DBManage:
が定義されています。

コードをコピー コードは次のとおりです:

クラス DBManage(オブジェクト):
@クラスメソッド
定義テーブル名(cls):
return cls.__name__. lower()

@classmethod
定義 select_all(cls​​):
sql = "SELECT * FROM %s""" % cls.table_name()
#このステートメントを実行するコード
結果を返します

これは実際にはデータベース内の特定のテーブルに対応する基本モデルであり、他のモデルがそれを継承し、table_name メソッド (現在はまだメソッド) を再利用することを願っています。

次のように User モデルを定義するだけです:

コードをコピー コードは次のとおりです:

クラス ユーザー(DBManage):
パス

次に、次のように Post モデルを定義します:
コードをコピー コードは次のとおりです:

クラスPost(DBManage):
パス

このように、すべての User データをチェックする必要がある場合は、User.select_all() だけが必要です。Post.select_all() についても同様です。しかしこの時、ちょっと嫌な事に気づきました。つまり、基本クラスの cls.table_name() コードです。 table_name は属性のように見えますが、メソッドを呼び出して取得する必要があります。不適切。

そこで、クラスプロパティをカスタマイズしました。

コードをコピー コードは次のとおりです:

クラスクラスプロパティ(オブジェクト):
Def __init__(self, func):
self.func = func

def __get__(self、instance、klass):
return self.func(klass)

これは次のようにする必要があります。DBManage のコードは次のように変更できます。

コードをコピー コードは次のとおりです:

クラス DBManage(オブジェクト):
@クラスプロパティ
定義テーブル名(cls):
return cls.__name__. lower()

@classmethod
定義 select_all(cls​​):
sql = "SELECT * FROM %s""" % cls.table_name # 直感的ですね


これは Descriptor の別の使用例です。
SQL で値を割り当てるときに、なぜ直接 sql = "SELECT * FROM %s" % cls.__name__. lower() を実行しないのですか?これはとても良い質問ですが、その理由は一言で言えば「怠惰」です。今後、毎回こんなにたくさんのコードを入力するのは面倒です。
声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。