![](http://oshiete.xgoo.jp/images/v2/pc/qa/question_title.png?8acaa2e)
Pythonのプログラミングの質問です。
今学校で習っているのですが、理解出来ないところがありましたので教えて頂けたらと思います。
関数を使って生年月日を分解して1の位まで足してでてくる数字を求めたいのですが、エラーがおこってしまいます。
私は最後の部分が違っていると思うのですが、どう直せばいいかわかりません。どなたか教えて頂けないでしょうか…。
以下がコードです。↓
print("あなたの生年月日の年を西暦で入力してください。")
y = input()
print("あなたの生年月日の月を入力してください。")
m = input()
print("あなたの生年月日の日を入力してください。")
d = input()
seinengappi = y + m + d
def kansu_suuzi(seinengappi):
while True:
a = 0
for i in seinengappi:
a += int(i)
if a < 10 or a==11 or a==22 or a==33 or a==44:
break
return a
seinengappi = str(a)
h = input()
kansu_suuzi(int(h))
print("1の位は…", h)
No.2ベストアンサー
- 回答日時:
・・・・・・こういう事したいのかしらん。
# ここから
print("あなたの生年月日の年を西暦で入力してください。")
y = input()
print("あなたの生年月日の月を入力してください。")
m = input()
print("あなたの生年月日の日を入力してください。")
d = input()
seinengappi = y + m + d
def kansu_suuzi(seinengappi):
a = sum([int(i) for i in list(seinengappi)])
while a > 9:
a = sum([int(i) for i in list(str(a))])
return a
h = kansu_suuzi(seinengappi)
print("1の位は・・・", h)
# ここまで
No.6
- 回答日時:
> 返り値と戻り値がまだ理解できていなく
返り値と戻り値は同じ意味です。
・・・うん、実はプログラミング初心者的には理解が難しい、ってのは不思議ではないんですよ。
初心者状態でその辺すんなり理解出来る人が半数くらい、そうじゃない人も半数くらい、ですかね(ちなみに僕も後者でした)。
そして「どのレベルで説明するのか」なかなか厄介なのも事実なんです。
例えば、ですね。「1足す2を計算しなさい」って問題があるとする。
バカみたいですが、これくらい簡単な問題を考えます。
往年のBASIC、ないしは古いスタイルのプログラミングとしてはこういう事をやったりしてました。
# 旧くてダメなスタイル
ans = 0
def hoge():
global ans
ans = 1 + 2
hoge()
print(ans)
## ここまで
ここで関数hogeは返り値を持ちません。そして関数hoge内部で大域変数ansを変更してる。
実は往年のプログラミングテクニックってこんなんばっかなんですよ。ぶっちゃけ、現在のC言語なんかでも似たような事をやらせてます(特に配列絡みで)。
一方、現代的なやり方は、多分貴方もコッチの方が馴染みがあるでしょうが、次のように書きます。
# 現代的なスタイル
def hoge():
return 1 + 2
print(hoge())
## ここまで
旧くてダメなスタイルと現代的なスタイルを比較してみれば分かるでしょうが、
・ 旧くてダメなスタイルは大域変数を設定してそれを書き換える、と言うカンジで答えを求めてる。
・一方、現代的なスタイルでは返り値を用いてる。そしてその場合、実行されてる関数を別の関数(この場合はprint)の引数にしても構わない。返り値をアテにして変数に代入する事も出来る
・旧くてダメなスタイルと現代的なスタイルを比較するとコード量は現代的なスタイルの方が少ない
ってのが違いです。特に二番目が返り値の大きな特徴、ないしは利用の仕方、ですね。
コンピュータサイエンス的に言うと、実は旧くてダメなスタイルで書かれている関数hogeは関数ではありません。コンピュータサイエンス的には手続き、あるいはプロシージャと呼びます。プロシージャは返り値を持たず、主に大域変数あるいは与えられたデータ(引数)を強制的に書き換える目的で作られます(もっと言うと、こういうのを「副作用目的」と言います)。
反面、関数の特徴は返り値を持つ事。場合によってはデータの書き換えはあり得るんですが、それを行う目的だけで作られる事はないのです。あくまで「返り値を返す」のが関数設計の目的です。
・手続き(プロシージャ)・・・・・・返り値が無い
・関数・・・・・・返り値がある
実際の話、Pythonでは全部が関数で、コンピュータサイエンス的な意味での「手続き」は「Noneを返す関数」と呼ばれてます。呼んで字の如く、返り値は自動的にNoneになる。
# 旧くてダメなスタイルをちょっと改造してみる
ans = 0
def hoge():
global ans
ans = 1 + 2
val = hoge() # 手続きhogeを実行して変数valに代入すると・・・・・・?
print(val) # valの中身はNoneになってる
# ここまで
もうちょっと理解を深める為に「1足す2足す3は何になるか」考えてみましょう。
これもデモンストレーションの為の問題なんで、実際はこんな、いずれにしてもバカな書き方はしないんですが、あくまでデモンストレーションの為、旧くてダメなスタイルと現代的なスタイルを比較してみます。
# 旧くてダメなスタイル
ans = 0
def hoge():
global ans
ans += 1
def fuga():
global ans
ans += 2
def piyo():
global ans
ans += 3
hoge()
fuga()
piyo()
print(ans)
## ここまで
# 現代的なスタイル
def hoge():
return 1
def fuga(x):
return x + 2
def piyo(x):
return x + 3
print(piyo(fuga(hoge())))
## ここまで
まぁ問題自体はバカバカしいんでどーでもいいんですが、現代的なスタイルの場合、もちろん各関数の実行結果をそれぞれ変数に代入可能なんですが(フツーはそういった書き方をするでしょう)、上のデモのように、引数に関数の実行結果を直接ツッコんじゃって連鎖させる事も可能です。
・・・まぁ、この辺、結果書いたコードの「可読性」とどう折り合いを付けるのか、ってのがあって、上の例だと「やり過ぎだ」って感じる人もいるでしょう。
ただ、関数の返り値って何?と言う疑問に直接答えるより「どう返り値を用いるか」の方が意味が明確に伝わる事もあって、そういう意味だと上の現代的なスタイルの例は分かりやすいかな、とは思います。
ちなみに、Pythonのprintも実は「Noneを返す関数」で、このようにしてprintの「返り値」を見る事が出来ます。
>>> x = print("hoge")
hoge
>>> print(x)
None
「"hoge"を印字する」と言う作用は実は返り値ではなくって、返り値自体はNoneだ、って事がこれで分かりますね。しかもxにprint("hoge")を代入してxを何度実行させても二度と"hoge"は印字されません。
つまり、print関数の主目的はコンピュータサイエンス的には「与えられた引数を印字する事」じゃないのです。不思議ですがそうなんです。そしてそれで分かるのは印字自体は「計算」ではない、と言う事実。こういう関数を「副作用目的の関数」等と呼びます。
コンピュータ上の入出力は理論的には実は不可思議な分野で、いずれにせよ、print等の入出力関数は、我々ユーザーは「主目的」には興味がない。「副作用目的」で使っているのです。
No.5
- 回答日時:
うーん、まずインデントは全角スペースに置き換えて
投稿した方がいいですよ。
半角スペースはこのサイトの仕様でみんな消えてしまうので・・・
pythonはインデントが命の言語だから削られるとなんだか
よくわからない。
No.4
- 回答日時:
そうね。
#3氏も言ってる通り、関数の引数、そして返り値の使い方が、どう見てもまだ分かってない気がする・・・・・・。
あとね、Pythonでそのままバッチ式の・・・と言うか、BASICみたいな書き方するのは端的に言うと「間違ってます」。まぁ、出来なくはないけどさ。
この辺、教えるセンセーにも拠るんだろうけど、バッチ式ガンガンやらせよう、初心者相手だから、ってのはPython使ったプログラミングの教育としては大間違いなんだよ。
たまに(いや、かなりの確率で?)Pythonで「C言語的な教育」をやろう、ってヤツいるんだけど、そもそも言語の設計方針に逆らった事やらせて上手く行く筈がないの。
言語設計に沿った教育が本当なら必要なのね。
あと、細かいトコ言うと、例えば
1. input関数でユーザーに入力促す際にprintを使うのは無駄。input関数は引数に「ユーザーへのメッセージ」を含む事が出来る。
例)
☓ ダメな書き方:
print("あなたの生年月日の年を西暦で入力してください。")
y = input()
○ 良い書き方:
y = input("あなたの生年月日の年を西暦で入力してください。\n")
input:
https://docs.python.org/ja/3/library/functions.h …
2. リストを使いこなす。Pythonに限らないけど、プログラミング言語ではリストや配列と言ったようなデータ構造をバンバン使う。特にこの問題のような「総和を求めよ」と言う場合、一々チマチマと変数を「足し合わせる」よりは、対象をリストとしてsum関数で和を取った方が早い。
例)
☓ ダメな書き方:
for i in seinengappi:
a += int(i)
○ 良い書き方:
例えば
>>> sum([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
55
等。
sum:
https://docs.python.org/ja/3/library/functions.h …
3. リスト内包表記を使いこなす事。
これは初心者には「難しい」と思ってる人が多いけどさに非ず。なるたけ初心者状態でこれを覚えなさい。少なくともPython設計者達はユーザーにこれを使いまくって欲しいと思っている。
繰り返しでforとかwhileを使いそうな際、書く前に「リスト内包表記が使えないか?」毎回自問する事。80%くらいはリスト内包表記を使えば問題はスムーズに解決する。特に2.との絡みで。
リストの内包表記:
https://docs.python.org/ja/3/tutorial/datastruct …
4. Pythonでバッチ式、ないしはBASIC的なプログラムを書きたい場合、シェバングとif __name__ == '__main__':に頼る事。必要な関数を定義したらそれをシェバングとif __name__ == '__main__':で挟んでしまって、必要なバッチ処理はif __name__ == '__main__':以降に記述する。
Pythonプログラムの先頭行の #! シバン(Shebang)について:
https://gammasoft.jp/python/python-shebang/
Pythonの if __name__ == ‘__main__’ の使い方【初心者向け】:
https://techacademy.jp/magazine/19129
5. Pythonでの代入は複数の代入を一行で記述する事が可能。それをやった方がPython「らしい」。
☓ ダメな書き方:
y = input("あなたの生年月日の年を西暦で入力してください。\n")
m = input("あなたの生年月日の月を入力してください。\n")
d = input("あなたの生年月日の日を入力してください。\n")
○ 良い書き方
y, m, d = input("あなたの生年月日の年を西暦で入力してください。\n"), \
input("あなたの生年月日の月を入力してください。\n"), \
input("あなたの生年月日の日を入力してください。\n")
まぁ、さすがにこういうケースの場合、一行で書くと辛かったりするので、一行があまりに長すぎる場合は"\"を入れてシンタックス上問題が無い、と言う事をインタプリタに通達して改行を行う事が出来る(これは関数の引数が長すぎる、ないしは多すぎる場合にも良く使われる手である)。
と言うわけで取り敢えずこの5つの心構えを用いて#2で書いたコードをより「Pythonらしく」書き直したのが次のコードです。
#!/usr/bin/env python3
def kansu_suuzi(seinengappi):
while len(seinengappi) > 1:
seinengappi = str(sum([int(i) for i in seinengappi]))
return seinengappi
if __name__ == '__main__':
y, m, d = input("あなたの生年月日の年を西暦で入力してください。\n"), \
input("あなたの生年月日の月を入力してください。\n"), \
input("あなたの生年月日の日を入力してください。\n")
print("1の位は・・・{}".format(kansu_suuzi(y + m + d)))
回答ありがとうございます。丁寧な説明本当に感謝しております。
返り値と戻り値がまだ理解できていなくて、どのサイトをみても理解できかったためここにのせました。
アドバイスを糧にやってみます。ありがとうございました。
No.3
- 回答日時:
関数引数の使い方に混乱がみられるようなので、そこらへん勉強してみては。
値を引数で戻すのではなく、returnで戻した値を使うようしたほうが良いかと。
今回の例だと、seinengappiが「00010101」から「99991231」までだとしたら、以下で計算できるかも:
seinengappi = '20210623'
h = (sum( int(x) for x in seinengappi ) - 1) % 9 + 1
print( seinengappi, 'の1の位は', h )
※ 2+0+2+1+0+6+2+3=16, 1+6=7
########
print("あなたの生年月日の年を西暦で入力してください。")
y = input()
print("あなたの生年月日の月を入力してください。")
m = input()
print("あなたの生年月日の日を入力してください。")
d = input()
seinengappi = y + m + d
def kansu_suuzi(seinengappi):
△while True:
△△a = 0
△△for i in seinengappi:
△△△a += int(i)
△△if a < 10 or a==11 or a==22 or a==33 or a==44:
△△△break
△△△return a
△△seinengappi = str(a)
h = input()
kansu_suuzi(int(h))
print("1の位は…", h)
回答ありがとうございます。
そうです、返り値がまだ理解できていません。
コード参考にさせていただきます。
ありがとうございました
No.1
- 回答日時:
うーん、インデントも無茶苦茶なんで何がやりたいんだかサッパリ分からんぞ・・・・・・。
例えば
return a
って書いてる以上、これは関数kansu_suuzi内にあるはずなんだけど、その後seinengappi = str(a)とか書かれてて、これは実行されないはずだし・・・。
そのあと
h= input()
になってて、そして
kansu_suuzi(int(h))
・・・。そうすれば最初に書かれてたy、m、dって言う変数も無意味になる。
全般的にホント、コード的には「何がやりたいんだかサッパリ分からん」コードになっています。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- その他(プログラミング・Web制作) 【Python初学者】以下コードについて教えていただきたいです 4 2023/04/19 13:01
- その他(プログラミング・Web制作) 全然分からず困っています。習ったものはPythonで基本的に for~in/if/n=len/inp 2 2023/05/23 21:47
- その他(プログラミング・Web制作) 全然分からず困っています。習ったものはPythonで基本的に for~in/if/n=len/inp 2 2023/05/23 22:00
- Ruby パイソンプログラミング 2 2022/12/03 18:44
- その他(プログラミング・Web制作) python質問 1 2023/08/14 11:54
- その他(プログラミング・Web制作) プログラミング python 3 2023/06/14 03:55
- Ruby プログラミング 3 2023/06/09 14:30
- PHP PHPでCookieを使った訪問回数について 1 2023/05/28 14:10
- その他(プログラミング・Web制作) atcoder python コードへの助言 2 2022/08/12 15:31
- その他(プログラミング・Web制作) python コードについて(初学者です) 3 2023/07/20 14:44
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
foreach 回数制限
-
Application.ScreenUpdating = ...
-
JSONで文字列が長い時
-
セレクトメニューで2つの項目...
-
メモリをアドレスを直接指定し...
-
文字の横にプルダウンを表示さ...
-
テーブル内でドロップダウンメ...
-
[Ruby] irbにおける文字化け
-
数値かどうかの判定方法
-
実行時エラー 3020の対策
-
エクセルVBA シート名の部分一...
-
変数名に変数を使用
-
formで特定のinputを送信しない...
-
phpでボタンを押したときに変数...
-
Python - Excel で Webからデー...
-
文字のカラーとフォントの指定...
-
子windowsからsubmit()後にclos...
-
【至急!!!】python言語で本を見...
-
FindFirst を複数条件で検索
-
16進の10進変換について
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
CLispのloop内の挙動について
-
Perlで自分自身の関数名を知る...
-
Net::Telnetでタイムアウト時間...
-
print <<"_HTML_"の中でサブル...
-
Rubyのgets関数について
-
10進数→2進数
-
CGI初心者です
-
Perlで複数の値を返す良い方法...
-
作業域が消える(ように見える)
-
検索機能の作成で困っています
-
Pythonのマルチプロセスでの並...
-
ハノイの塔の問題で困っており...
-
LISPで連想配列の操作?
-
PERLの「!=」と「=~」 or...
-
PerlでCabochaを呼び出すには(...
-
foreach 回数制限
-
シェルでawkを使い行数を取り出...
-
Wコロン
-
HASH(0xほげほげ)
-
プロトタイプ宣言のワーニング...
おすすめ情報