Python で組み込み関数 property() をいつ、どのように使用するか
質問
ちょっとした構文上の工夫を除いて、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
といった具合に、プロパティを介して使用しないようにしましょう。
プロパティが実装を隠してしまうという苦情は全く正当化されません:ほとんどの はすべて つまり、クラスが外界に対して論理的なインターフェイスを提示する責任を負い、内部では可能な限りそれを実装することです。ゲッターとセッターは、まさにプロパティと同じように、この目標に向けたツールです。プロパティは、(それをサポートする言語では)より良い仕事をするだけです。
関連
-
[解決済み] 関数デコレータを作成し、それらを連鎖させるには?
-
[解決済み] Pythonで現在時刻を取得する方法
-
[解決済み] Pythonで2つのリストを連結する方法は?
-
[解決済み] ファイルのコピー方法について教えてください。
-
[解決済み] 最小限の驚き」と「変更可能なデフォルトの引数
-
[解決済み] フィールドとプロパティの違いは何ですか?
-
[解決済み] Pythonの@propertyデコレーターはどのように機能するのでしょうか?
-
[解決済み】ネストされたディレクトリを安全に作成するには?
-
[解決済み】__str__と__repr__の違いは何ですか?
-
[解決済み] DataFrameに日付間の日数カラムを追加する pandas
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] 前月の日時オブジェクトを返す
-
[解決済み] PythonでのAWS Lambdaのインポートモジュールエラー
-
[解決済み] なぜ(0-6)は-6=偽なのか?重複
-
[解決済み] オブジェクトのリストに特定の属性値を持つオブジェクトが含まれているかどうかをチェックする
-
[解決済み] サブフォルダからのインポートモジュール
-
[解決済み] djangoフレームワークでフォームフィールドから値を取得するには?
-
[解決済み] Pythonによる一対のクロスプロダクト [重複] (英語)
-
[解決済み] Pandasのデータフレーム内の文字列を'date'データ型に変換するにはどうしたらいいですか?
-
[解決済み] Pythonでランダムなファイル名を生成する最良の方法
-
[解決済み] Django テンプレートで関連する項目を並べ替える