pythonのメゾッドの整合性について

このQ&Aのポイント
  • pythonの文字列はオブジェクトであり、特定のメゾッドを使うことで変換や操作ができます。
  • 文字列のメゾッドはオブジェクト自体を変化させるのではなく、新しいオブジェクトを返す仕様となっています。
  • 一方、リストのメゾッドはオブジェクト自体を変化させます。
回答を見る
  • ベストアンサー

pythonのメゾッドの整合性について

こんばんは。 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'] のような振る舞い方を行うのが"正しい"と思うのですがなぜ違うのでしょうか?

質問者が選んだベストアンサー

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

Pythonのリファレンスマニュアルより 5. 組み込み型 http://docs.python.jp/2.7/library/stdtypes.html 5.6.4. 変更可能なシーケンス型 http://docs.python.jp/2.7/library/stdtypes.html#typesseq-mutable 注釈 7 > sort() および reverse() メソッドは大きなリストを並べ替えたり反転したりする際、容量の節約のためにリストを直接変更します。副作用があることをユーザに思い出させるために、これらの操作は並べ替えまたは反転されたリストを返しません。 sort,reverseについては、このように説明があります。 変更不可(immutable)なオブジェクトに対しての、破壊的メソッドはありません。破壊的であるならば、それは「変更可能」ということを意味するからからです。 同様に、変更可能(mutable)なオブジェクトには、破壊的メソッドが存在します。そうでなれば、変更可能である意味が無いからです。 やり方に正解も不正解もありません。 Pythonの設計者達は、この方法がいいと思ったから、この方法を採択したのでしょう。

その他の回答 (6)

回答No.7

回答No.6へ 今どき、JavaScriptでも文字列は不変で、配列は可変なので、ある意味軽量言語界ではこの区別は常識という感じです。 それで困った事がないので、問題ないのだと思います。 感覚的には、不変な型のほうが相対的に少ないので、すぐ気づく感じでしょうか。 なお、Pythonにおいて自作クラスを不変な型にするのは、一手間あった記憶があります。なにもせず放っておくと勝手に可変な型という扱いになる感じです。(破壊的メソッドがなくとも) とはいえ、自作クラスを不変な型にするメリットは、辞書のキーに使えるぐらいしか無いので、あまりしたいとは思いません。

回答No.6

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

回答No.5

No.4にもうちょい追加で。 pythonの組み込み型では一般的に、可変なオブジェクトがあったとき  オブジェクト.sort() はオブジェクトが変わる  オブジェクト.reverse() はオブジェクトが変わる だけど  sorted(オブジェクト) はオブジェクトは変わらない(新規に生成される)  reversed(オブジェクト) はオブジェクトは変わらない(新規に生成される) となるみたい。 なお、不変な型は何をしてもオブジェクトは変わらない。

回答No.4

> >>> 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などでも、守られていない場合が結構ある。

  • unya_unya
  • ベストアンサー率54% (19/35)
回答No.2

#1です。先にも書きましたが、ます、もうちょっと勉強して、実際にプログラムを書いてみましょう。 自然と分かるようになりますよ。 今、誰かに回答をしてもらっても、理解できるとは思えません。

pipopipoid
質問者

お礼

そうですか がんばります

  • unya_unya
  • ベストアンサー率54% (19/35)
回答No.1

まず、まだ初心者なんだから下手な類推をするよりも、マニュアルや入門書、入門サイトを読んで勉強しましょう。 このハナシは、オブジェクト指向とはあまり関係がありません。 どちらかといえば、関数型プログラミングに関係が深いハナシです。 メソッドは、オブジェクトの中身を変更するものとしないものの2つに分けられます。 前者を「破壊型」、後者を「非破壊型」といいます。 最初の例のstr.upperは、あなたの理解どおり、strオブジェクトの内容を変更しない、非破壊型です。 これに対して、list.reverseは、listの内容を変更(並び準が逆になってしまう)する破壊型のメソッドです。 str.upperメソッドの方は、非破壊型であり、strオブジェクトの値を変更できないのですから、 大文字に変更した結果の文字列を新たに生成して、戻り値として返します。 一方、list.reverseの実行結果は、list自体に残されているため、戻り値として返す必要がありません。 だから、戻り値がNoneで何の不都合もありません。 変更後のlist自体を戻り値として返すこともできますが、そうすると、str.upperのように、新たなオブジェクトを 生成しているようにも見え、かえって誤解を招く動作とも言えます。 ですから、ある程度、勉強した人は、この動作の方が「正しい」と感じるようになります。 ちなみに、strオブジェクトはimmutableと言われます。その値を変更できない、ということです。 >>> strA = strA.upper() という処理の実行前と実行後では、変数strAが指すオブジェクトが違うオブジェクトを指しているのであり、 strAが指すオブジェクトの中身が変わったのではありません。ここの違いを理解することは大切です。

pipopipoid
質問者

お礼

> str.upperメソッドの方は、非破壊型であり、strオブジェクトの値を変更できないのですから、 大文字に変更した結果の文字列を新たに生成して、戻り値として返します。 一方、list.reverseの実行結果は、list自体に残されているため、戻り値として返す必要がありません。 だから、戻り値がNoneで何の不都合もありません。 変更後のlist自体を戻り値として返すこともできますが、そうすると、str.upperのように、新たなオブジェクトを 生成しているようにも見え、かえって誤解を招く動作とも言えます。 はい、この部分は理解しています。 僕がわからないのは、あなたが新しく教えてくださった語句によるところの 破壊的メゾッドと非破壊的メゾッドが混在しているのはなぜか、という部分です。 どちらかに統一する方が簡単ではないかと思ったからです。 str型がimmutableであり、list型はimmutableではないこと、つまり immutableなものに対しては非破壊的メゾッド、immutable出ないものに対しては破壊的メゾッドが備わっていると解釈すべきですか?

関連するQ&A

  • Pythonでのプログラミングについて。

    Pythonでのプログラミングについて。 大学の授業でPythonが出たのですが、なんせ先生が適当すぎてさっぱり意味がわかりません・・; 以下の問題の答えか、もしくは解説してくれる方はいらっしゃいませんでしょうか。 Q1:オレンジの数(count)を受け取って、"Number of oranges:<count>"を返すorange関数(a)を書け。 ただし、countが10以上の場合は実際の値のかわりに"many"を使え。 def orange(count): (a) return str print orange(4) print orange(99) Q2:文字列を受け取って、最初と最後の各2文字から作成した文字列を返すboth_ends関数(b)を書け。 ただし、文字列の長さが1のときは空文字列を返せ。 def both_ends(coun): (b) return str print both_end("hello") print both_end("a") Q3:文字列を反転するプログラム(c)を書け。 orig="hello" (c) print result Q4:文字列を反転するreverse関数(d)を書け。 (d) orig="good" result=reverse(orig) print result Q5:キーボードから受け取った文字列が回文(palindrome)かどうか判定するプログラム(e)を書け。 (d) orig=raw_input("Type a phrease:") result=reverse(orig) (e) Type a phrease:alice reverse=ecila Type a phrease:anna **palindrome** 自分で本を読んだり色々調べてみたのですが、判りませんでした。。 今日の12時までなのですが、誰かお願いします(;_;)

  • python 代数を定義

    list = ['a', 'b', 'c', 'd'] X = list .pop() print(list) このコードを実行すると、print(list) の結果として ['a', 'b', 'c'] が得られることになります。 しかし私としては、['a', 'b', 'c', 'd']とならないのが不可解なのです。 なぜなら、2行目の X = list .pop() は代数Xを定義しているにすぎず、リストであるlistには影響を与えていないと思うのです。 (print(X) が ['a', 'b', 'c'] となれば納得するのですが、もちろんこの答えはdとなります。) pythonの文法上なぜこうなるのか教えて頂きたいです。

  • python ですが下記のプログラムがエラーになり

    python ですが下記のプログラムがエラーになります。どうしてでしょうか。よろしくお願い致します。 def revers(data): for index in range(len (data)-1,-1,-1): yield data[index] some_list = [‘a’, ‘b’, ‘c’, ‘d’] for e in revers(some_list): print(e) 実行結果をd      c      b      a にしたいのですがエラーがでます。

  • Pythonのreadlineについて

    最近Pythonのプログラミングを始めたのですが、Pythonのプログラミングについて以下のことを行いたいのですが、やり方が分からず困っております。 Pythonで行いこと 1.textファイルに例えば以下のようにいくつかの係数を入力しておきます。 a:0.5, b:0.8, c:0.9 2.上記のテキストファイルを読み込み、pythonの変数a、b、cに値を格納したいと考えています。 色々検索している中でテキストファイルの読み込みはf=open(xxx.txt)で読み込み、各行の読み込みはreadline()というコマンドでできることは分かったのですが、lines=f.readline()とした後、その"line"の中からaが0.5、bが0.8という数字部分だけを切り出してプログラム中の変数に渡す方法が分からない状態です。 皆様のお知恵を拝借いたしたく、宜しくお願いいたします。

  • Python の構文について

    Pythonを学び始めたばかりのPython初心者です。 Pythonでは、 #!/usr/bin/env python principal = 1000 # Initial amount rate = 0.05 # Interest rate numyears = 5 # Number of years year = 1 while year <= numyears : principal *= 1 + rate print("%3d %0.2f" % (year, principal)); # Reminder: print(year, principal)in P3 year += 1 のような書き方をしますが、条件式をCみたいに()でくくったり、ブロック{}を使う方法は無いのでしょうか? (式の最後に;をつける事は出来るのです。) ()や{}を使った方が見やすいので、出来れば()や{}を使いたいと思っています。 よろしくお願いします。

  • pythonにCでのexternはありますか

    python初心者です。 a.py, b.pyがあります。 <a.py> import b bar=123 b.foo() <b.py> def foo  global bar  print bar 実行すると"123"が表示されず失敗します。 Cだとexternすれば外部参照で希望通りに成功します。 CとPythonは違うことは知っていますが、Pythonで実現できないでしょうか。 又は類似の手段はありますか。

  • Python について質問です

    私はPythonの初心者です。 今Python でCSVのファイルを読んで数値だけ(数値以外に文字列や空白などがあります)を計算処理出来なくて困っています。教えて頂けませんか? 質問は、BB.csvというファイルの数値だけの合計と平均を計算したいです。 私のコードは以下です。 # coding: utf-8 import csv import re import string DATAFILE = 'BB.csv' class UnicodeDictReader(csv.DictReader): def __init__(self, f, fieldnames=None): csv.DictReader.__init__( self, f, fieldnames) def main(): total = 0 all_sum = 0 line_num = 0 with open(DATAFILE) as csvfile: reader = UnicodeDictReader(csvfile) for record in reader: # 値を数値で取得 A = int(record['38186']) B = int(record['38181']) C = int(record['38143']) item_total = A + B + C total = item_total all_sum += item_total line_num += 1 average = all_sum / reader.line_num print(" %d + %d + %d = %d " % ( A, B, C, total)) print(u"合計 %d " % all_sum) print(u"平均 %d " % average) if __name__ == '__main__': main() BB.csvは以下です、 38186,38181,38143 1,1,4 1,1,4 ,, ,, 2020,2020,2020 1412,1412,1412 625,625,625 75,75,75 75,75,75 75,75,75 75,75,75 4,4,4 4,4,4 4,4,4 7828,7828,7828 X,, 0,0,0 0,0,0 ○,, 0,0,0 0,0,0 0,0,0 ,,AAA 0,0,0 0,0,0 0,0,0 ,BBB, 0,0,0 0,0,0 0,0,0 ,, 0,0,0 ,, 0,0,0 0,0,0 ,, 0,0,0 0,0,0 750,750,750 400,400,400 400,400,400 ,, 0,0,0 0,0,0 0,0,0 ,, 0,0,0 0,0,0 0,0,0 0,0,0 0,0,0 0,0,0 0,0,0 6,6,6 6,6,6 18,18,18 18,18,18 18,18,18 18,18,18 18,18,18 16,16,16 16,16,16 6,6,6 6,6,6 18,18,18 18,18,18 18,18,18 18,18,18 18,18,18 11,11,11 11,11,11 11,11,11 3,3,3 3,3,3 3,3,3 3,3,3 4,4,4 4,4,4 3,3,3 3,3,3 16,16,16 16,16,16 16,16,16 14,8,11 8,14,11 8,14,11 8,14,11 8,14,11 8,14,11 8,14,11 8,14,11 8,14,11 15,15,15

  • Python:ifについて

    Python初心者です。 ある変数(a,b,c)で条件A(a<b+c and b<a+c and c<b+a)があるとする。 ・条件Aを満たさない場合:0 ・条件Aを満たしたうち、  条件Bを満たす:1  条件Cを満たす:2  条件Dを満たす:3 このように「Aがtrueの中で、別の条件を満たす場合~」とういうのはどのように書けばいいでしょうか。

  • python >の意味

    お世話になっております。pythonを勉強しておりまして、星座を求めるコードを見たのですが最後の行のコードが理解できませんでした。 print a[ m-13 + (d > b[m-1]) ] の>というのはどういう意味なのでしょうか。 よろしくお願いいたします。 # -*- coding: utf-8 -*- a = [u'山羊座', u'水瓶座', u'魚座', u'牡羊座', u'牡牛座', u'双子座', u'蟹座', u'獅子座', u'乙女座', u'天秤座', u'蠍座', u'射手座'] b = [20, 19, 20, 20, 20, 21, 23, 23, 23, 23, 22, 22] m = int(raw_input('月を入力してください: ')) d = int(raw_input('日を入力してください: ')) print a[ m-13 + (d > b[m-1]) ]

  • python

    pythonについての質問です。 def S_sa(k=1) for step in xrange(k) : if step == 0 : print 'a' else print 'b' というコードがあって、なぜかprint aが実行されるのはなぜでしょうか? xrangeのreturnは1ではないのでしょうか?

専門家に質問してみよう