Python 記述子の入門

Dec 05, 2016 pm 01:27 PM
python

長い間 Flask のコードについて書いていなかったのですが、思い出すと本当に恥ずかしいです。それでも今回は書きません。受け入れられない場合は、私に叩きに来てください。私はとても雌犬です、できれば噛んでください)

今回はPythonでとても重要なDescriptorについて書きます

記述子の最初の紹介

古いルール、話は安い、まずコードを見てみましょう

リーリー

この世代では誰もがプロパティについてよく知っているはずですが、プロパティの実装メカニズムをご存知ですか?何が不明ですか? Pythonを勉強してみてはいかがでしょうか? 。 。冗談はさておき、次のコードを見てみましょう

リーリー

複雑だと思いませんか? 順を追って見ていきましょう。しかし、ここで最初に結論を示します。記述子は特別な種類のオブジェクトであり、__get__、__set__、__delete__ という 3 つの特別なメソッドを実装します。

ディスクリプタの詳しい説明

物件について話す

上記では、プロパティの実装コードを示しました。次に、これについて詳しく説明します

リーリー

まず、デコレータについて知らない場合は、この記事を読んでください。つまり、コードを正式に実行する前に、インタープリタがコードをスキャンして、関連するコードをチェックします。クラスデコレータについても同様です。上記では、このコード

リーリー

はそのようなプロセス、つまり full_name=Property(full_name) をトリガーします。次に、後でオブジェクトをインスタンス化した後、person.full_name を呼び出します。このプロセスは実際には person.full_name.__get__(person) と同等であり、__get__() メソッドに記述された return self.fget(obj) をトリガーします。オリジナル 上記は我々が書いたdef full_nameの実行コードです。

この時点で、同志は getter()、setter()、deleter()= の具体的な操作メカニズムについて考えることができます。 =まだ質問がある場合は、コメントでお気軽にご相談ください。

記述子について

前に説明した定義を思い出してください。記述子は、__get__、__set__、__delete__ という 3 つの特別なメソッドを実装する特別な種類のオブジェクトです。次に、公式 Python ドキュメントの説明には、記述子の重要性を反映するために、次の段落があります。「記述子は、プロパティ、メソッド、静的メソッド、クラス メソッド、および super() の背後にあるメカニズムです。これらは Python 全体で使用されます」つまり、最初に記述子があり、次に空があり、次に空気が来ます。新しいスタイルのクラスでは、属性、メソッド呼び出し、静的メソッド、クラス メソッドなどはすべて、記述子の特定の使用法に基づいています。

OK、なぜ記述子がそれほど重要なのかと疑問に思うかもしれません。心配しないで、続けて見てみましょう

記述子を使用する

まず、次のコードを見てください

classA(object):#注意: Python 3.x バージョンでは、Python 2.X (x>2) の場合、新しいクラスを使用するためにオブジェクト クラスからの継承を明示的に指定する必要はありません。バージョン、必須です

リーリー

このようなステートメント a.a() があることに誰もが気づいています。さて、このメソッドを呼び出すと何が起こるか考えてください。

いいですか?もう分かりましたか?いいえ?はい、続けましょう

まず、属性を呼び出すとき、それがメンバーであってもメソッドであっても、呼び出そうとする属性が実装されている場合、__getattribute__() メソッドで属性 __getattribute__() を呼び出すメソッドがトリガーされます。記述子プロトコルの場合、type(a).__dict__['a'].__get__(b,type(b)) のような呼び出し処理が生成されます。さて、ここで別の結論が得られます: 「そのような呼び出しプロセスには、そのような優先順位があります。呼び出しようとしている属性がデータ記述子の場合、この属性がインスタンスの __dict__ に存在するかどうかに関係なく、辞書では、記述子の __get__ メソッドが最初に呼び出されます。呼び出そうとしている属性がデータ記述子ではない場合、インスタンス内の __dict__ 内の既存の属性が優先されます。対応する原則は次のとおりです。次に、クラスと親クラスの __dict__ に含まれる属性を検索します。属性が存在しない場合は、__get__ メソッドが呼び出されます。少し抽象的でわかりにくいですか?大丈夫、すぐに取り掛かりますが、ここではまずデータ記述子と非データ記述子について説明し、それから例を見てみる必要があります。データ記述子と非データ記述子とは何ですか?実際、記述子に __get__ プロトコルと __set__ プロトコルの両方を実装する記述子は、__get__ プロトコルのみを実装する場合はデータ記述子ではありません。さて、例を見てみましょう:

リーリー

好的,让我们仔细来看看这段代码,首先类描述符 @lazyproperty 的替换过程,前面已经说了,我们不在重复。接着,在我们第一次调用 c.area 的时候,我们首先查询实例 c 的 __dict__ 中是否存在着 area 描述符,然后发现在 c 中既不存在描述符,也不存在这样一个属性,接着我们向上查询 Circle 中的 __dict__ ,然后查找到名为 area 的属性,同时这是一个 non data descriptors ,由于我们的实例字典内并不存在 area 属性,那么我们便调用类字典中的 area 的 __get__ 方法,并在 __get__ 方法中通过调用 setattr 方法为实例字典注册属性 area 。紧接着,我们在后续调用 c.area 的时候,我们能在实例字典中找到 area 属性的存在,且类字典中的 area 是一个 non data descriptors ,于是我们不会触发代码里所实现的 __get__ 方法,而是直接从实例的字典中直接获取属性值。

描述符的使用

描述符的使用面很广,不过其主要的目的在于让我们的调用过程变得可控。因此我们在一些需要对我们调用过程实行精细控制的时候,使用描述符,比如我们之前提到的这个例子

classlazyproperty:
def__init__(self, func):
 self.func = func

def__get__(self, instance, owner):
ifinstanceisNone:
returnself
else:
 value = self.func(instance)
 setattr(instance, self.func.__name__, value)
returnvalue

def__set__(self, instance, value=0):
pass


importmath


classCircle:
def__init__(self, radius):
 self.radius = radius
pass

 @lazyproperty
defarea(self, value=0):
 print("Com")
ifvalue ==0andself.radius ==0:
raiseTypeError("Something went wring")

returnmath.pi * value *2ifvalue !=0elsemath.pi * self.radius *2

deftest(self):
pass

ログイン後にコピー

利用描述符的特性实现懒加载,再比如,我们可以控制属性赋值的值

classProperty(object):
"Emulate PyProperty_Type() in Objects/descrobject.c"
def__init__(self, fget=None, fset=None, fdel=None, doc=None):
 self.fget = fget
 self.fset = fset
 self.fdel = fdel
ifdocisNoneandfgetisnotNone:
 doc = fget.__doc__
 self.__doc__ = doc

def__get__(self, obj, objtype=None):
ifobjisNone:
returnself
ifself.fgetisNone:
raiseAttributeError("unreadable attribute")
returnself.fget(obj)

def__set__(self, obj, value=None):
ifvalueisNone:
raiseTypeError("You can`t to set value as None")
ifself.fsetisNone:
raiseAttributeError("can't set attribute")
 self.fset(obj, value)

def__delete__(self, obj):
ifself.fdelisNone:
raiseAttributeError("can't delete attribute")
 self.fdel(obj)

defgetter(self, fget):
returntype(self)(fget, self.fset, self.fdel, self.__doc__)

defsetter(self, fset):
returntype(self)(self.fget, fset, self.fdel, self.__doc__)

defdeleter(self, fdel):
returntype(self)(self.fget, self.fset, fdel, self.__doc__)

classtest():
def__init__(self, value):
 self.value = value

 @Property
defValue(self):
returnself.value

 @Value.setter
deftest(self, x):
 self.value = x

ログイン後にコピー

如上面的例子所描述的一样,我们可以判断所传入的值是否有效等等。

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

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

Video Face Swap

Video Face Swap

完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

PHPおよびPython:さまざまなパラダイムが説明されています PHPおよびPython:さまざまなパラダイムが説明されています Apr 18, 2025 am 12:26 AM

PHPは主に手順プログラミングですが、オブジェクト指向プログラミング(OOP)もサポートしています。 Pythonは、OOP、機能、手続き上のプログラミングなど、さまざまなパラダイムをサポートしています。 PHPはWeb開発に適しており、Pythonはデータ分析や機械学習などのさまざまなアプリケーションに適しています。

PHPとPythonの選択:ガイド PHPとPythonの選択:ガイド Apr 18, 2025 am 12:24 AM

PHPはWeb開発と迅速なプロトタイピングに適しており、Pythonはデータサイエンスと機械学習に適しています。 1.PHPは、単純な構文と迅速な開発に適した動的なWeb開発に使用されます。 2。Pythonには簡潔な構文があり、複数のフィールドに適しており、強力なライブラリエコシステムがあります。

Python vs. JavaScript:学習曲線と使いやすさ Python vs. JavaScript:学習曲線と使いやすさ Apr 16, 2025 am 12:12 AM

Pythonは、スムーズな学習曲線と簡潔な構文を備えた初心者により適しています。 JavaScriptは、急な学習曲線と柔軟な構文を備えたフロントエンド開発に適しています。 1。Python構文は直感的で、データサイエンスやバックエンド開発に適しています。 2。JavaScriptは柔軟で、フロントエンドおよびサーバー側のプログラミングで広く使用されています。

Visual StudioコードはPythonで使用できますか Visual StudioコードはPythonで使用できますか Apr 15, 2025 pm 08:18 PM

VSコードはPythonの書き込みに使用でき、Pythonアプリケーションを開発するための理想的なツールになる多くの機能を提供できます。ユーザーは以下を可能にします。Python拡張機能をインストールして、コードの完了、構文の強調表示、デバッグなどの関数を取得できます。デバッガーを使用して、コードを段階的に追跡し、エラーを見つけて修正します。バージョンコントロールのためにGitを統合します。コードフォーマットツールを使用して、コードの一貫性を維持します。糸くずツールを使用して、事前に潜在的な問題を発見します。

VSCODE拡張機能は悪意がありますか? VSCODE拡張機能は悪意がありますか? Apr 15, 2025 pm 07:57 PM

VSコード拡張機能は、悪意のあるコードの隠れ、脆弱性の活用、合法的な拡張機能としての自慰行為など、悪意のあるリスクを引き起こします。悪意のある拡張機能を識別する方法には、パブリッシャーのチェック、コメントの読み取り、コードのチェック、およびインストールに注意してください。セキュリティ対策には、セキュリティ認識、良好な習慣、定期的な更新、ウイルス対策ソフトウェアも含まれます。

Windows 8でコードを実行できます Windows 8でコードを実行できます Apr 15, 2025 pm 07:24 PM

VSコードはWindows 8で実行できますが、エクスペリエンスは大きくない場合があります。まず、システムが最新のパッチに更新されていることを確認してから、システムアーキテクチャに一致するVSコードインストールパッケージをダウンロードして、プロンプトとしてインストールします。インストール後、一部の拡張機能はWindows 8と互換性があり、代替拡張機能を探すか、仮想マシンで新しいWindowsシステムを使用する必要があることに注意してください。必要な拡張機能をインストールして、適切に動作するかどうかを確認します。 Windows 8ではVSコードは実行可能ですが、開発エクスペリエンスとセキュリティを向上させるために、新しいWindowsシステムにアップグレードすることをお勧めします。

PHPとPython:彼らの歴史を深く掘り下げます PHPとPython:彼らの歴史を深く掘り下げます Apr 18, 2025 am 12:25 AM

PHPは1994年に発信され、Rasmuslerdorfによって開発されました。もともとはウェブサイトの訪問者を追跡するために使用され、サーバー側のスクリプト言語に徐々に進化し、Web開発で広く使用されていました。 Pythonは、1980年代後半にGuidovan Rossumによって開発され、1991年に最初にリリースされました。コードの読みやすさとシンプルさを強調し、科学的コンピューティング、データ分析、その他の分野に適しています。

ターミナルVSCODEでプログラムを実行する方法 ターミナルVSCODEでプログラムを実行する方法 Apr 15, 2025 pm 06:42 PM

VSコードでは、次の手順を通じて端末でプログラムを実行できます。コードを準備し、統合端子を開き、コードディレクトリが端末作業ディレクトリと一致していることを確認します。プログラミング言語(pythonのpython your_file_name.pyなど)に従って実行コマンドを選択して、それが正常に実行されるかどうかを確認し、エラーを解決します。デバッガーを使用して、デバッグ効率を向上させます。

See all articles