- 締切済み
Python: matrix追加でNoneの理由
下記の#入力とPython #コード の実行で、「出力結果」が出ます #▼Aのところで、 matrix.append(d) を可視化しようとしたら None しか返りません 想像では入力の2行目以降が順次追加されていくイメージを想像していました [[11, 14, 16, 9]] [[11, 14, 16, 9], [11, 14, 16, 9]] : 質問: 1)この#▼Aの下の行でNoneしか返らない理由をおしえてください 2)matrixに追加されて形成される行列は、単純にメモリ上で形成されていると考えていいですか? #入力 3 11 14 16 9 13 15 19 10 10 11 14 11 #コード N = int(input()) # 空のリストを作成 matrix = [] for i in range(N): # 入力を受け取り、リストに変換 d = list(map(int, input().split())) # リストをmatrixに追加 matrix.append(d) #▼Aここでmatrixを可視化しようとした print(matrix.append(d)) print(app) #▼Bここでもmatrixを可視化しようとした print(matrix) # 1行目の要素0 first_element = matrix[0][0] print(first_element) #11 #==出力結果================== None None None None None None [[11, 14, 16, 9], [11, 14, 16, 9], [13, 15, 19, 10], [13, 15, 19, 10], [10, 11, 14, 11], [10, 11, 14, 11]] 11
- みんなの回答 (7)
- 専門家の回答
みんなの回答
- cametan_42
- ベストアンサー率62% (162/261)
プログラミング初めたばっか、なのかね。 ええと、コンピュータサイエンス的な話をまずはする。 構造化プログラミング、と言う手法が一般的になってから、処理単位を纏める、と言う方法論が普及した。 一般に、「関数」って呼ばれる事になるんだけど、厳密に言うと二種類存在する。 一つは「返り値」を持つ「関数」。もう一つは「返り値」を持たない「手続き」(あるいはプロシージャ、と呼ぶ)。 コンピュータサイエンス上はこの二種類で「処理を纏める」わけだ。 で、返り値(あるいは戻り値とも呼ぶ)とは何か。 それは関数終了時に「返された値」の事。 例えばこういう単純な関数を考えてみる。 def foo(): return "hoge" これが関数、だ。これを実行すると「"hoge"と言う文字列の値が返ってくる」んで、適当な変数に代入出来たり、あるいは他の関数の引数として使える。 >>> foo() 'hoge' >>> x = foo() >>> x 'hoge' >>> print(foo()) hoge Pythonで関数の書き方はreturnを使う事。return 返したい計算結果、で上の例のように返り値を変数に代入したり、他の関数(上の例ではprint)の引数として使う事が出来る。 一方、Pythonでは明示的な手続き(プロシージャ)の作り方は存在しない。 と言うか、C言語登場以降、明示的な手続き作成の方法を持たないプログラミング言語の方が多くなった。C言語では「返り値がvoidな関数」が手続きを表す。 同様に、Pythonでは手続きは「Noneを返す関数」と呼ばれる。 もう一回繰り返す。関数は返り値を返す為にある。 一方、手続き(プロシージャ)は何の為にあるのか、と言うと「副作用目的」の為にあるんだ。 コンピュータサイエンス上、「副作用」と言うのが何か、と言うと「計算と関係ない作業」の事を指す。具体的には「代入」とか「入出力」なんかは計算と関係ないんで、これらは全部副作用だ。 多分この辺になるとピンと来なくなってくるだろうけど(笑)、覚えておいた方がいい概念だ。 手続きは次のように使うんだ。 >>> lst = [1, 2] >>> def bar(): ... lst[0] = 3 ... ... >>> bar() >>> lst [3, 2] 例えば最初に大域変数lstを定義する。中身は[1, 2]だ。 次に手続き(プロシージャ)barを定義する。大域変数lstの第0要素に3を「代入」する。副作用目的なんでreturnしない。 barを実行後、lstの第0要素は3に変更されている。 これが代表的な手続き(プロシージャ)の作り方と使い方だ。 一方、この「プロシージャによって大域変数を代入によって変更する」ってのは現代的には褒められたプログラミングスタイルじゃない。モダンなプログラミングスタイルでは、基本的には関数は引数を取り、返り値を返すようにデザインすべきだ。 しかしながら一般的に例外があって、オブジェクト指向プログラミング、と言われるスタイルだと、クラス(データ型設計法の一つ)が持つ操作関数、メソッドとかメンバ関数って呼ばれるんだけど、はプロシージャル(手続き的)な設計をしてるケースが多いんだ。 Pythonのデータ型に付随しているメソッドのその殆どはプロシージャルな設計が成されている。appendメソッドもそうだ。だから返り値を持たない。 個人的な意見では、あまり良い設計方針ではないんだよ(笑)。ただ、Pythonはそういう設計になってるメソッドが多くて、だから組み込みのメソッドを使う時には気をつけないといけない。貴方のように混乱するのも当然と言えば当然だ。 これはホント、プログラミング言語の設計方針次第、なんだ。 だから、 > 想像では入力の2行目以降が順次追加されていくイメージを想像していました 例えばPythonと競合した、と思われたRubyなんかだと、貴方の想像通りの動作になるんじゃないか。 Rubyでのコード例: https://www.ideone.com/LBGPNj 形式的にはPythonのコードとそこまで差異はなく、貴方の書いたコードのロジックをそのまま追って置き換えてるんで、読むのはさして難しくないだろう。 かつ実行結果はこんなカンジだ。 3 11 14 16 9 [[11, 14, 16, 9], [11, 14, 16, 9]] [[11, 14, 16, 9], [11, 14, 16, 9], [11, 14, 16, 9]] 13 15 19 10 [[11, 14, 16, 9], [11, 14, 16, 9], [11, 14, 16, 9], [13, 15, 19, 10], [13, 15, 19, 10]] [[11, 14, 16, 9], [11, 14, 16, 9], [11, 14, 16, 9], [13, 15, 19, 10], [13, 15, 19, 10], [13, 15, 19, 10]] 10 11 14 11 [[11, 14, 16, 9], [11, 14, 16, 9], [11, 14, 16, 9], [13, 15, 19, 10], [13, 15, 19, 10], [13, 15, 19, 10], [10, 11, 14, 11], [10, 11, 14, 11]] [[11, 14, 16, 9], [11, 14, 16, 9], [11, 14, 16, 9], [13, 15, 19, 10], [13, 15, 19, 10], [13, 15, 19, 10], [10, 11, 14, 11], [10, 11, 14, 11], [10, 11, 14, 11]] [[11, 14, 16, 9], [11, 14, 16, 9], [11, 14, 16, 9], [13, 15, 19, 10], [13, 15, 19, 10], [13, 15, 19, 10], [10, 11, 14, 11], [10, 11, 14, 11], [10, 11, 14, 11]] 11 多分、これが貴方が望んだ結果だろう。 Rubyは設計上、オブジェクト指向のメソッドはPythonと違って「必ず返り値を持つ」ようになってる為、Noneが返る、みたいな事がないんだ。 結果、appendメソッドで代入しようと、必ず代入が行われた側のデータが返り値として返ってくる。 繰り返すけど、「言語の設計方針」によってこの辺は違う。Pythonのオブジェクト指向だとプロシージャルな設計が基本となっている。 なお、老婆心から言うと、プログラミング初心者段階だとこのテのメソッドは使わないようにした方が良い。Python入門書だととにかく最初にこのテのリストのメソッドを紹介して「使え」的なカンジになってるが、元々これらはプログラムを書き終わった後に「最適化」として導入すべきものだ。つまり、本来なら「使いどころ」が分からん時点だと導入しない方がいいんだ。 貴方のこのコードの例でも、これは「バグを書いちゃった」って事になる。キチンと使いどころが分からん以上、使わん方がいい。 恐らく貴方が本当に書きたかったプログラムは次のようなモノだろう。 実装例: https://www.ideone.com/myWh9J プログラムを書く際に気をつける事を列挙しておく。 1. 処理を纏めて関数を作ろう 2. Pythonではリスト内包表記を使いこなそう 3. 関数に入出力を埋め込まずに切り離そう 4. 入出力が要り用になる場合は、if __name__ == '__main__':以降に書き、プログラムがキチンとスクリプトとして成立するようにしよう この4つが肝要かな。 関数定義: https://docs.python.org/ja/3/reference/compound_stmts.html#function-definitions リスト内包表記: https://docs.python.org/ja/3/tutorial/datastructures.html#list-comprehensions __main__ --- トップレベルのスクリプト環境: https://docs.python.org/ja/3/library/__main__.html 以上。
- Kaneyan-R
- ベストアンサー率42% (1340/3126)
>print(app) >が >app = matrix.append(d) >print(app)でした はいそうですか。そこはどうでも良いのですけどね。 print(matrix.append(d)) が問題なので。 あなたが出力したいのは「追加された後のmatrixの中身」ではないのですか? 間違えたと言うところを訂正すると print(matrix.append(d)) app = matrix.append(d) print(app) となりますよね。 と、なると一回の入力で NONE NONE になるので、3回やればNONEが6回出力される。 で、matrix.append(d)のあとにprint(matrix.append(d))をやってるので、dの追加を2回やってることになります。 ※printするのは「matrix.append(d)の戻り値」なので、matrix.append(d)を実行しないといけない。 なので、matrixには同じものが2つずつ出来てしまうと言う結果になる。 と言うことで、 print(matrix.append(d)) app = matrix.append(d) print(app) の3行は、 print(matrix) だけで良いのです。
- chie65536(@chie65535)
- ベストアンサー率44% (8740/19838)
>app = matrix.append(d) >print(app)でした こうしたとしても matrix.append(d)は「Noneを返す」ので matrix.append(d) app = None print(app) と同じ意味になります。つまり matrix.append(d) print(None) と同じ事です。
お礼
ありがとうございました またよろしくお願いします
- chie65536(@chie65535)
- ベストアンサー率44% (8740/19838)
https://step-learn.com/article/python/046-list-append.html に「(append関数の)戻り値はNoneです。」と書いてあります。 #▼Aでは「append関数の戻り値を表示している」ので「append関数の戻り値であるNoneが表示されている」ので、それで正常です。 もし「append関数の戻り値は、追加後の状態のリストです。」だったら、#▼Aで「追加後のリストが可視化」できますが、そういう仕様にはなっていない(Noneが返される仕様になっている)ので、可視化出来ません。 Noneが返される関数の戻り値をprintしたら「None」と表示されて当たり前です。 「自分が何をprintしているのか?」を、もう少し考えてみて下さい。
お礼
戻り値がNoneという仕様でしたら納得です どうもNull(空っぽ)が返るというイメージにとらわれていたようです ありがとうございました
- _kappe_
- ベストアンサー率68% (1581/2304)
>matrix.append(d)の戻り値がNone >の意味がわかりません >関数でNoneを返していないのですが、ここでNoneが返る理由を教えていただけたら幸いです append()の仕様を作った人が「Noneを返す」と決めたからです。 https://docs.python.org/ja/3.11/tutorial/datastructures.htmlを見てください。「insert, remove, sort などのリストを操作するメソッドの戻り値が表示されていないことに気が付いたかもしれません。これらのメソッドは None を返しています。」と書かれています。
- _kappe_
- ベストアンサー率68% (1581/2304)
1) print(matrix.append(d))は「matrix.append(d)の戻り値をプリントせよ」という意味になりますが、matrix.append(d)の戻り値がNoneなので、Noneが出力されています。 1行入力するごとにmatrixの状態をprintで出力したければ、print(matrix.append(d))ではなくprint(matrix)と書いてください。 質問文に書かれているコードだと、▼Aの上のmatrix.append(d)と▼Aの下の print(matrix.append(d))で2回appendを実行してしまっています。3行分のデータを入力したのに▼Bの下のprint(matrix)の出力結果では6行分になっているのはそのせいです。 2) どんなイメージをお持ちなのか分かりませんが、変数matrixに代入されている行列のデータは実行中のPythonプロセスのメモリー内に保持されています。
お礼
print(app) がタイプミスに気づかず投稿してしまいました ちなみに matrix.append(d)の戻り値がNone の意味がわかりません 関数でNoneを返していないのですが、ここでNoneが返る理由を教えていただけたら幸いです
- Kaneyan-R
- ベストアンサー率42% (1340/3126)
Pythonはやったこと無いけど…… >print(matrix.append(d)) print(matrix) じゃないの? x.append(d)は「xに追加しろ」と言う命令なので、命令にデータは無いですよね? 日本語的にも「“matrixに追加しろ”を出力しろ」っておかしくない?「“matrixに追加した結果、matrixがどうなったか”を出力しろ」ならわかるけど。
補足
print(app) が app = matrix.append(d) print(app)でした
お礼
matrixがリストの形がでてほしい、ではなく、Noneが返る理由がわからないという質問でした 戻り値がNoneという仕様でしたら納得です ありがとうございました
補足
なお前も書きましたが、プログラマーではありません