1. ホーム
  2. python

Python で組み込み関数 property() をいつ、どのように使用するか

2023-09-05 21:14:50

質問

ちょっとした構文上の工夫を除いて、property()は何の役にも立たないように見えます。

確かに、以下のように書くことができるのはいいことです。 a.b=2 の代わりに a.setB(2) のように、予期しない結果が起こる可能性があるためです。 a.b=2 が実際に a.b になります。 1 . または例外が発生する。あるいはパフォーマンスの問題。あるいは単に混乱する。

良い使い方の具体例を教えてください。(問題のあるコードにパッチを当てるために使うのはカウントされません ;-)

どのように解決するのですか?

Java のようなゲッターとセッターに依存する言語では、ゲッターとセッターは、それらが言うこと以外のことをすることは想定されていませんし、期待もされていません。 x.getB() が論理属性の現在の値を返すこと以外何もしなかったとしたら、それは驚くべきことでしょう。 b である場合、あるいは x.setB(2) を作るために必要な、どんな小さな内部作業でも、何もしなかったとしたら。 x.getB() を返す 2 .

しかし、言語的に強制されることのない 保証 で始まるメソッドの本体に対するコンパイラによる制約です。 get または set というように、常識や社会通念、スタイルガイド、そしてテストに委ねられています。

の動作は x.b のようなアクセスや代入は x.b = 2 のようなアクセスや代入は、プロパティを持つ言語(Pythonを含むがこれに限定されない一連の言語)においては まさに であり、例えばJavaのゲッターとセッターのメソッドと同じです:同じ期待、言語によって強制される保証の欠如です。

プロパティの最初の利点は、構文と読みやすさです。 書かなければならないのは、たとえば

x.setB(x.getB() + 1)

の代わりに

x.b += 1

は神々に復讐するために叫びます。 プロパティをサポートする言語では、クラスのユーザーにこのようなビザンチン式の定型文を通過することを強制する正当な理由は全くありません。

Pythonでは特に、ゲッターとセッターの代わりにプロパティ(または他の記述子)を使用することに、もう1つの大きな利点があります。基本的なセッターとゲッターがもう必要ないようにクラスを再編成する場合、(クラスの公開APIを壊すことなく)単にそれらのメソッドとそれらに依存するプロパティを削除することができ、これにより b の通常の "stored"属性として使用することができます。 x のクラスの属性であり、計算によって取得および設定される "論理的"のものではありません。

Pythonでは、メソッドを介さずに(可能な限り)直接行うことは重要な最適化であり、プロパティを体系的に使用することで可能な限りこの最適化を行うことができます(常に通常の保存属性を直接公開し、アクセスや設定時に計算が必要なもののみをメソッドやプロパティで公開します)。

したがって、もしあなたがプロパティの代わりにゲッターとセッターを使用するならば、ユーザーのコードの可読性に影響を与える以上に、あなたは マシン サイクル (およびそのサイクル中にコンピュータに供給されるエネルギー) を無条件に浪費していることになります。 また を、何の理由もなく無駄にしています。

あなたのプロパティに対する唯一の主張は、例えば、"外部のユーザーは通常、代入の結果としてどんな副作用も期待しないでしょう"ですが、同じユーザーが(ゲッターとセッターが普及しているJavaのような言語で)セッターを呼んだ結果として(観察可能)"副作用を期待しない(そしてゲッターについてはさらに少ない)という事実を見落としています。これらは合理的な期待であり、クラスの作者であるあなたがそれに応えようとするのは勝手です。あなたのセッターとゲッターが直接使われるか、プロパティを通して使われるかは、何の違いもありません。 もし、観察可能な重要な副作用を持つメソッドがあるのなら、次のようにしてください。 ではない 名付ける getThis , setThat といった具合に、プロパティを介して使用しないようにしましょう。

プロパティが実装を隠してしまうという苦情は全く正当化されません:ほとんどの はすべて つまり、クラスが外界に対して論理的なインターフェイスを提示する責任を負い、内部では可能な限りそれを実装することです。ゲッターとセッターは、まさにプロパティと同じように、この目標に向けたツールです。プロパティは、(それをサポートする言語では)より良い仕事をするだけです。