プロが教えるわが家の防犯対策術!

こんばんは。
pythonを勉強し始めましたが理解できない部分があって質問させて頂きます。
プログラム、特にオブジェクト指向をまだよく理解していないのである程度初心者向けの回答をお願いします。

pythonにおいて文字列はオブジェクトであり、

>>> strA = "python"
>>> print (strA)
python
>>> print (strA.upper())
PYTHON
>>> print (strA)
python

のように使われるメゾッドが存在しています。
これはオブジェクト自体を変化させるのではなく、今回の場合ではオブジェクトがupper()されたオブジェクトを返しています(まちがっていませんよね?)。

そのため、strA自体を変化させるには

>>> strA = strA.upper()
>>> print (strA)
PYTHON

のようにする必要があると理解していました。
ここで新しいオブジェクトlistを用いた時

>>> tl = ['A','B','C','D','E','F']
>>> print (tl)
['A', 'B', 'C', 'D', 'E', 'F']
>>> print(tl.reverse())
None
>>> print(tl)
['F', 'E', 'D', 'C', 'B', 'A']
>>> listA.reverse()

となります。文字列から類推すると

>>>tl = ['A','B','C','D','E','F']
>>>print (tl.reserve())
['F', 'E', 'D', 'C', 'B', 'A']
>>>print(tl)
['A','B','C','D','E','F']
>>>tl =tl.reserve()
>>>print (tl)
['F', 'E', 'D', 'C', 'B', 'A']

のような振る舞い方を行うのが"正しい"と思うのですがなぜ違うのでしょうか?

A 回答 (7件)

Pythonのリファレンスマニュアルより



5. 組み込み型
http://docs.python.jp/2.7/library/stdtypes.html

5.6.4. 変更可能なシーケンス型
http://docs.python.jp/2.7/library/stdtypes.html# …
注釈 7
> sort() および reverse() メソッドは大きなリストを並べ替えたり反転したりする際、容量の節約のためにリストを直接変更します。副作用があることをユーザに思い出させるために、これらの操作は並べ替えまたは反転されたリストを返しません。

sort,reverseについては、このように説明があります。


変更不可(immutable)なオブジェクトに対しての、破壊的メソッドはありません。破壊的であるならば、それは「変更可能」ということを意味するからからです。
同様に、変更可能(mutable)なオブジェクトには、破壊的メソッドが存在します。そうでなれば、変更可能である意味が無いからです。


やり方に正解も不正解もありません。
Pythonの設計者達は、この方法がいいと思ったから、この方法を採択したのでしょう。
    • good
    • 0

回答No.6へ



今どき、JavaScriptでも文字列は不変で、配列は可変なので、ある意味軽量言語界ではこの区別は常識という感じです。
それで困った事がないので、問題ないのだと思います。
感覚的には、不変な型のほうが相対的に少ないので、すぐ気づく感じでしょうか。

なお、Pythonにおいて自作クラスを不変な型にするのは、一手間あった記憶があります。なにもせず放っておくと勝手に可変な型という扱いになる感じです。(破壊的メソッドがなくとも)
とはいえ、自作クラスを不変な型にするメリットは、辞書のキーに使えるぐらいしか無いので、あまりしたいとは思いません。
    • good
    • 0

 ごめんなさい。

回答ではないのですが、面白かったのでコメントします。

 メソッドに定数的なものと変数的なものがあるのは便利そうですね。
ただ、その使用に際して明確な違いがないとコードを見た際にそのメソッドが
どうゆう挙動をするのかが直感的に解りにくいのはデバッグの時などに、特に
言語に馴染んでない場合など苦労しそうです。
 現状では、メソッドを変数に代入する際に変数名で差別化するのが賢明な
対処なのでしょうが、出来れば言語レベルでの明確な差別化が欲しいところですね。

プログラムの学習頑張ってください。
    • good
    • 0

No.4にもうちょい追加で。



pythonの組み込み型では一般的に、可変なオブジェクトがあったとき
 オブジェクト.sort() はオブジェクトが変わる
 オブジェクト.reverse() はオブジェクトが変わる

だけど
 sorted(オブジェクト) はオブジェクトは変わらない(新規に生成される)
 reversed(オブジェクト) はオブジェクトは変わらない(新規に生成される)

となるみたい。
なお、不変な型は何をしてもオブジェクトは変わらない。
    • good
    • 0

> >>> strA = "python"


> そのため、strA自体を変化させるには
>
> >>> strA = strA.upper()
> >>> print (strA)
> PYTHON
>
> のようにする必要があると理解していました。

これは、strA自体を変化させるというよりは・・・

strA ---> "python"
  の状態から、
"python" ===オブジェクトを新規生成===> "PYTHON"
  そして
strA --x リンクを外す x--> "python"
  からの
"PYTHON" <--- 新たにリンク付け--- strA

という感じ。文字列は『不変』でしょ?
(変数とオブジェクトのリンクが変わっただけ)

不変なもの: 数値、文字列、タプル
可変なもの: リスト、その他ほとんどのクラスのオブジェクト

実際、Pythonの哲学として、「規約なんてどうせすぐ破られる」というのが有るのではないでしょうか。
だからRubyのように、「末尾に ! がついてるメソッドを呼ぶと壊れる、かもね(※)」みたいな中途半端なお約束は一切せずに、
型として不変/可変を決めておいて、不変な型であれば絶対変わりませんよ(ここはRubyなども同じ)。あとは可変なオブジェクトのメソッドが破壊的であるかどうかは、それぞれ個々のマニュアルを読んでね(面倒だけど、始めから守れないと分かりきってるルールを決めるよりマシ)。というスタンスなのです。

だからかどうか知りませんが、PythonではRubyと違い、文字列は不変ですし、不変なリストとしてタプルがあります。
不変な型が多めなので、あまり困った事はありません。変えたくなければ不変な型を使えばいいのです。

文字列が不変であることで、不便な場合もありますが、反面、変わらない安心感があります。
私は安心感が有る方がいいです。(Rubyでは不変な文字列としてシンボルを用意しましたが、だったら文字列が不変でいいじゃないかと・・・)

※:実際、ruby on railsなどでも、守られていない場合が結構ある。
    • good
    • 0

#1です。

先にも書きましたが、ます、もうちょっと勉強して、実際にプログラムを書いてみましょう。
自然と分かるようになりますよ。

今、誰かに回答をしてもらっても、理解できるとは思えません。
    • good
    • 0
この回答へのお礼

そうですか
がんばります

お礼日時:2013/08/12 13:40

まず、まだ初心者なんだから下手な類推をするよりも、マニュアルや入門書、入門サイトを読んで勉強しましょう。



このハナシは、オブジェクト指向とはあまり関係がありません。
どちらかといえば、関数型プログラミングに関係が深いハナシです。

メソッドは、オブジェクトの中身を変更するものとしないものの2つに分けられます。
前者を「破壊型」、後者を「非破壊型」といいます。

最初の例のstr.upperは、あなたの理解どおり、strオブジェクトの内容を変更しない、非破壊型です。
これに対して、list.reverseは、listの内容を変更(並び準が逆になってしまう)する破壊型のメソッドです。

str.upperメソッドの方は、非破壊型であり、strオブジェクトの値を変更できないのですから、
大文字に変更した結果の文字列を新たに生成して、戻り値として返します。

一方、list.reverseの実行結果は、list自体に残されているため、戻り値として返す必要がありません。
だから、戻り値がNoneで何の不都合もありません。
変更後のlist自体を戻り値として返すこともできますが、そうすると、str.upperのように、新たなオブジェクトを
生成しているようにも見え、かえって誤解を招く動作とも言えます。

ですから、ある程度、勉強した人は、この動作の方が「正しい」と感じるようになります。


ちなみに、strオブジェクトはimmutableと言われます。その値を変更できない、ということです。

>>> strA = strA.upper()

という処理の実行前と実行後では、変数strAが指すオブジェクトが違うオブジェクトを指しているのであり、
strAが指すオブジェクトの中身が変わったのではありません。ここの違いを理解することは大切です。
    • good
    • 0
この回答へのお礼

>
str.upperメソッドの方は、非破壊型であり、strオブジェクトの値を変更できないのですから、
大文字に変更した結果の文字列を新たに生成して、戻り値として返します。

一方、list.reverseの実行結果は、list自体に残されているため、戻り値として返す必要がありません。
だから、戻り値がNoneで何の不都合もありません。
変更後のlist自体を戻り値として返すこともできますが、そうすると、str.upperのように、新たなオブジェクトを
生成しているようにも見え、かえって誤解を招く動作とも言えます。

はい、この部分は理解しています。
僕がわからないのは、あなたが新しく教えてくださった語句によるところの
破壊的メゾッドと非破壊的メゾッドが混在しているのはなぜか、という部分です。
どちらかに統一する方が簡単ではないかと思ったからです。

str型がimmutableであり、list型はimmutableではないこと、つまり
immutableなものに対しては非破壊的メゾッド、immutable出ないものに対しては破壊的メゾッドが備わっていると解釈すべきですか?

お礼日時:2013/08/12 12:21

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!