class C(object):
@property
def x(self):
"I am the 'x' property."
return self._x
@x.setter
def x(self, value):
self._x = value
@x.deleter
def x(self):
del self._x
>もっとも、「何を取得するときはプロパティとして実装し、何を取得するときはメソッドとして実装するか」というのは、難しい問題です。 コードを複数の人が共有する場合は、プロパティとメソッドの使い分けの共有が難しいなぁ、と思いました。 とはいえ、1番目のサンプルコードで、read only なプロパティ(例:email)は、プロパティメソッドで定義する、変更可能なプロパティは、直接変更可能という使い方のイメージができました。
藤本 博子さんの投稿
(投稿ID: 5426)
実際にどのようなケースで使われることが多いのか気になりました。
@propertyをCntl+Bで定義をみると、builtins.py4267行目に飛び、dogstringsに以下の通り、Property attributeが書かれてました。
値を呼び出す時には@propertyで呼び出す
値を変更するときは@プロパティ名.setterを呼び出す。
予期せぬ値が入り込まないように、'setter'で値を制限するというような使われ方がするのか気になりました。
builtins.py 4267行目
値を呼び出す時には@propertyで呼び出す
値を変更するときは@name.setterを呼び出す。
値が未入力の場合は、@name.setterでエラーを出す、いうような使われ方がするのか気になりました。
小川 慶一さんのコメント
(コメントID: 7997)
以下はシンプルかつ簡明なサンプル。
@property デコレータがなければ、 john.email() とか john.full_name() とかと、メソッド呼び出しの形で値を取得することになります。
もっとも、「何を取得するときはプロパティとして実装し、何を取得するときはメソッドとして実装するか」というのは、難しい問題です。
settter とか deleter とかは、使えるようにならなくて良いかと思います。
Pythonは、「外部からアクセス/変更できないようにプロテクトする」といった保守的な(*)実装があまり好まれない言語です。
メソッド等の名称をアンダーバー「 _ 」ではじまるものにし、「これはいじらないでね」という意図を示す程度のことはありますが。
setter とか deleter のようなものも、少なくとも僕が見る範囲では、最近書かれたと思しきのソースコードではほぼ見かけないです。
上のサンプルであれば、 john.last_name = 'Harrison' といった感じで直接編集してOKです。
(コメントアウトされている最終行のように、 email のような read only なプロパティはどのみち変更できません)
たとえば「first_name は __init__ で設定させ、以降は変更させたくない」ということであれば、以下のように、受け取った値を _first_name 等、先頭がアンダーバーの名前のインスタンス変数に格納すると良いでしょう。
(*)
「保守的な」という言い方は適切かどうかは分かりませんが、まあニュアンスは伝わるかと。
エクセルVBAすら、Public/Private キーワードがあってPrivateなものはプロテクトできるのに、Pythonにはこのようなキーワードすらありません。
藤本 博子さんのコメント
(コメントID: 8001)
ご回答くださいまして、ありがとうございます。
>もっとも、「何を取得するときはプロパティとして実装し、何を取得するときはメソッドとして実装するか」というのは、難しい問題です。
コードを複数の人が共有する場合は、プロパティとメソッドの使い分けの共有が難しいなぁ、と思いました。
とはいえ、1番目のサンプルコードで、read only なプロパティ(例:email)は、プロパティメソッドで定義する、変更可能なプロパティは、直接変更可能という使い方のイメージができました。
また、2番目のサンプルコードでプライベートな属性と”意図を示す”事例をご提示いただきました。
他の人のコードを読む際に、このように書かれていたら、その意図を読み取れるようにしたいと思います。
>Pythonは、「外部からアクセス/変更できないようにプロテクトする」といった保守的な(*)実装があまり好まれない言語です。
メソッド等の名称をアンダーバー「 _ 」ではじまるものにし、「これはいじらないでね」という意図を示す程度のことはありますが。
setter とか deleter のようなものも、少なくとも僕が見る範囲では、最近書かれたと思しきのソースコードではほぼ見かけないす。
>「first_name は __init__ で設定させ、以降は変更させたくない」ということであれば、以下のように、受け取った値を _first_name 等、先頭がアンダーバーの名前のインスタンス変数に格納すると良いでしょう。
解説いただき、大変勉強になります。
ありがとうございました。
小川 慶一さんのコメント
(コメントID: 8003)
>コードを複数の人が共有する場合は、プロパティとメソッドの使い分けの共有が難しいなぁ、と思いました。
まず前提として書くと、「プロパティとメソッド」の違いはこれです!」という万国共通の区分けみたいなものはないです。
以下のページの Excel VBA のコードなんかは典型例です。
Worksheets の Activate メソッドは、Pythonのカラブルとは異なり、 () を取りませんね。
一方、セルの Offset プロパティは、 () を後ろに取って、かつ、引数まで受け取っています。(どう見ても、「これって、メソッドだろ!」という感じですが... (^^; )
https://learn.microsoft.com/ja-jp/office/vba/api/excel.range.offset
ということで、どう切り分けても、「誰もが納得」という切り方はできません。
量をこなしていくうちに、自分なりの基準ができあがる。
そして、その基準も、書いていくうちに(また、他の言語での実装に触れていくうちに、時代が変化していくうちに)変わっていくことと思います。
自分の中で基準がそれなりにできあがるまでは、テキトーで良いかと思います。
...とはいえ、迷ったらメソッドですかね。
@property て書くのは面倒ですし。(ほかにも理由はありますが)
藤本 博子さんのコメント
(コメントID: 8005)
ご回答ありがとうございます。
@propertyというデコレータの使いどころや基準は、お手本のコードを読んだり、自分でコードを書いて経験値が増えるうちに、自分なりにできてくる。エクセルVBAは、プロパテイ、メソッドの基礎的な知識をベースとし、あとは特に難しいことを考えず書いています。
まずは量をこなしていくことが大切だなぁ、と思いました。
人が書いたコードに@proretyがあっても、意図は理解できるようになれたと思います。
小川先生のおっしゃる通り、
>そして、その基準も、書いていくうちに(また、他の言語での実装に触れていくうちに、時代が変化していくうちに)変わっていくことと思います。
ということもありそうですね。
>.とはいえ、迷ったらメソッドですかね。
@property て書くのは面倒ですし。(ほかにも理由はありますが)
自分もそうしたいと思います。
ご回答いただき、もやもやが晴れました。ありがとうございます。