• 締切済み

pythonにおけるメッセージについて

pythonでクラスを書き、オブジェクトを作りそこにメッセージを送ることでオブジェクトの属性を変化させる、というのがオブジェクト指向であると学んでいました。 ここで >>> import zlib >>> s = 'witch which has which witches wrist watch' >>> t = zlib.compress(s) というのは圧縮する機械にメッセージを送ったら圧縮されたメッセージが出てくるイメージになります。 ここで 文字列を継承して圧縮関数?を加えた実装を考えます >>> s = 'witch which has which witches wrist watch' >>> t = s.compress("zip") これはそもそも可能でしょうか?できるとしてなぜ前者の実装となるのでしょうか? オブジェクト指向、というとオブジェクトにメッセージを送るとそのメッセージによってオブジェクトの変数が操作されると考えてきました。 そうなると後者のほうが正しように感じられます

みんなの回答

  • wetti
  • ベストアンサー率66% (2/3)
回答No.3

オブジェクト指向にはいくつか派閥があってですね、 > オブジェクトを作りそこにメッセージを送ることでオブジェクトの属性を変化させる これはSmalltalk派の説明ですね。 PythonはどちかというとSimula派なので、 型や継承システムの方が重要っぽいです。 t = zlib.compress(s) のzlibは単なるモジュールなので、 オブジェクトというより単なる入れ物という意味合いが強いです。 つまりzlibに中に整理分けされているcompress関数を使っているだけ。 t = s.compress("zip") という書き方はできるのかというと、 実は Python 2.x までは似たような書き方ができた。 >>> s = 'witch which has which witches wrist watch' >>> s.encode('zlib') さすがに圧縮と文字エンコーディングは違うと気づいたのか、 3.xでは削られましたが。 > 文字列を継承したクラスであってもモジュールに分割することはできるのではないでしょうか? そういう設計にできないことはないんと思うけど、 Pythonにはまだトレイトの概念がないので微妙。

pipopipoid
質問者

お礼

ありがとうございました。オブジェクト指向にも複数方針があってそこまで原理主義的ではないんですね

  • kmee
  • ベストアンサー率55% (1857/3366)
回答No.2

まず。 t = zlib.compress(s) は ・zlibモジュールオブジェクトに「sを圧縮しろ」というメッセージを送る(メソッドを使用) ・zlibモジュールオブジェクトは、それに応じて「圧縮されたs」をメッセージとして返す(戻り値) (・返してきたメッセージを変数tとして記憶する) ということです。 これは、オブジェクト指向の操作として正しい、ということはよろしいですね? となると、「どちらが正しい」という絶対的なものではなく「どちらがより有用であるか」という相対的あるいは思想的なものになります。 私は、前者が妥当と思います。 後者は「文字列を操作するようなメソッドは、文字列型のメソッドとして実装すべきだ」という考えになります。 その考えに従えば、正規表現モジュールre等も、文字列クラスにならなければなりません。 自作した「文字列の末尾に"0"を追加した文字列を返すメソッド」も、文字列クラスのメソッドとして定義しなければなりません。 この手法でいけば、文字列(を継承した)クラスは、とても大規模なものになります。 大規模なプログラムは、それだけ間違いも多くなり、それを探すのに苦労するようになります。 モジュール毎に分割すれば、そのモジュールとしての機能にのみ注目すればよくなります。 オブジェクト指向の目的は、正しいプログラムを楽に作ることです。 どんなメッセージでも受け付ける完璧なオブジェクトを作ることではありません。 Pythonでの実装となると、その言語環境特有の問題もあります。 strを継承して、メソッドを追加するなら def compress(self,t)   if t="zip":     return zip.compress(self) という感じになるでしょう。結局、圧縮用オブジェクトに圧縮してもらうことになります。 こういうことをしない、となると、strに組込むしかなく、ソースコードからの変更が必要となります。 > s = 'witch which has which witches wrist watch' Pythonの変数には、型はありません。 オブジェクトにラベルを付ける、程度のものでしかありません。 文字列リテラルは、あくまで文字列型です。いわば s = str('witch which has which witches wrist watch') と書いてあるようなものです。 compressを追加した文字列 CompressibleString を定義したとして、この変数sをCompressibleStringにしたいのなら s=CompressibleString( 'witch which has which witches wrist watch') 等コンストラクタとして書くとか s=ConvertToCompressibleString( 'witch which has which witches wrist watch') 等と変換メソッドを使うとかして、CompresibleString型にする必要があります。 これらは、定数以外にも、既存の関数の戻り値等、CompressibleStringを使いたい全ての文字列に必要です。 うかつに s.compress("zip") とすると、変換忘れがあるとメソッドが無いのでエラーになります。

pipopipoid
質問者

お礼

文字列を継承したクラスであってもモジュールに分割することはできるのではないでしょうか? 後から付け加える際に大変になる、ということは納得できました

  • kmee
  • ベストアンサー率55% (1857/3366)
回答No.1

> オブジェクトの属性を変化させる 間違いです。 属性を変化させることは、必須ではありません。 なお、Pythonには、「変更不可」というクラスが多くあります。 文字列もその一つです。

pipopipoid
質問者

お礼

変更は不可ですが変更した文字列を返すことはできますよね 必須ではない、というだけではなぜ前者かとまではわからないのでもう少し詳しくお願いできませんか

関連するQ&A