電子書籍の厳選無料作品が豊富!

プログラミング初心者で、pythonを勉強しています。生徒の成績を付けるプログラムを書いていて、それぞれ50点満点で「技能」「考え方」「知識」の項目の点数を入力し、それぞれをパーセンテージによってA、B,Cで三段階評価し、
さらにA=3、B=2、C=1とし、その合計を3で割った値を5段階評価し、それを総合評価として出力したいです。

しかし、以下のコードを実行すると、各項目の結果が2回ずつ表示されます。
<コード>counter = 0
ginou = 0
kangae = 0
chishiki = 0

while True:
ginou = ginou + int (input ("技能"))
kangae = kangae + int (input ("考え方"))
chishiki = chishiki + int (input("知識"))
counter += 1
ask = int(input ("continue?(y=1,n=0)"))
if ask == 1:
continue


elif ask == 0:
def hyotei(tensuu):
if tensuu /counter /50 *100 >= 90:
print ("A",tensuu /counter /50 *100,"%")
return 3
elif tensuu / counter /50 *100 >=60:
print ("B",tensuu /counter /50 *100,"%")
return 2
elif tensuu / counter / 50 *100 <60:
print ("C",tensuu /counter /50 *100,"%")
return 1

hyotei(ginou)
eva = hyotei(ginou)
hyotei(kangae)
eva2 = hyotei (kangae)
hyotei(chishiki)
eva3= hyotei (chishiki)

if (eva + eva2+eva3)/3>=2.9:
print("総合評価:5")
elif (eva + eva2+eva3)/3>=2.6:
print("総合評価:4")
elif (eva + eva2+eva3)/3>=1.8:
print("総合評価:3")
elif (eva + eva2+eva3)/3>=1.3:
print("総合評価:2")
elif (eva + eva2+eva3)/3<1.3:
print("総合評価:1")
break


<技能50、考え方40、知識20の場合の実行結果>
A 100.0 %
A 100.0 %
B 80.0 %
B 80.0 %
C 40.0 %
C 40.0 %
総合評価:3

おそらくeva = hyoutei(ginou) のところの書き方が悪いのではと思っていますが、どうすれば結果を一回ずつ表示することができるでしょうか。

よろしくお願いします。

A 回答 (2件)

> 例えば出力はまったくせずに、returnで帰ってくる数値だけを参照して計算したりするばあいはどうしたらいいでしょうか。



基本的には返り値は、

1. 変数に代入するように持っていく
2. 別の関数の引数にツッコむ

の二種類の使い方をします。どっちでも好きなようにして構いません。

> eva=3 のとき
> print(hyotei(ginou)+5)
> だと、計算結果の8以外に、A 100.0 %という出力結果が出てしまいます。

それはhyoutei内にprintを仕込んでるからですね。hyoutei内からprintを外した方が良いでしょう。

ええと、「綺麗なプログラミングをしたい」と言う場合、入力、出力を「計算のキモ」となる関数から外した方が良いです。まあ、プログラミング書法的な考え方ですが、「入力は入力だけでまとめる」「出力は出力だけでまとめる」のが見通しが良いです。

ちょっと専門的な話になりますが、「関数は返り値を返し」ますが、その為に(現代の高級言語的には)「計算の結果を返す」場合は関数を作る、と言うセオリーを形作っています。
一方、実は入出力ってのは「計算」じゃないんですよ。こういう「計算と全く関係ない作用」を専門的には「副作用」と呼びます。

Python3では「printは関数」って事になってますが、実はこれは「副作用目的」の関数なんですね。
C言語やLispだとこういう「出力関数」ってのは印字と別に何かしらの返り値を持ってるんですが、Python3の場合、

>>> x = print("hello")
hello
>>> x
>>>

と、xには何も代入されません。Python3だと「Noneを返す関数」と言う表現を使いますが、実は一般的なプログラミング用語だとこれは関数ではないのです。こういう「返り値が何もない計算以外の目的(副作用目的)に使う何か」を手続き、あるいはプロシージャと呼びます。つまり、一般的にはPythonのprintは関数ではなくてプロシージャなんです。

注: これ、Pascal辺りだと厳密に関数とプロシージャが分かれてるんですが、高級言語もどんどん高級になるに従って境界線が曖昧になってきてて、Pythonの「Noneを返す関数」もそういう一例ですね。ちなみにC言語のvoid関数ってのも要するにプロシージャです。

まあ、ちょっと説明が難しいかもしれませんが、要するに、「綺麗なプログラムを書きたい」場合、「関数とプロシージャを混ぜ合わせない」ってのがコツで、プロシージャの何が一番頻出するのか、と言うと、やっぱ「入出力」なんですよ。こいつが関数内だと「邪魔」なんで、混ぜるな危険(笑)、ってワケで、切り分けるようにした方が見通しが良い、つまり「後々、修正が容易になる」って事ですね。
いずれにせよ、入出力を噛ませるのは「最後にプログラムをまとめる時」って覚えておいた方が後々良いのではないでしょうか。
    • good
    • 0
この回答へのお礼

なるほど、まだ勉強し始めて3週間ほどですが、綺麗なコードというのは今まで意識したことなかったですね。
丁寧に教えていただきありがとうございました!

お礼日時:2018/09/14 20:58

うーん、正直言って・・・・。


酷いコードですね。
いや、初心者だって事は分かってるんだけど、教本が良くないのじゃないかしらん。
バッチ式プログラミングになっています。
しかも、期せずしてローカル関数定義になってるし・・・・・・。
まあ、「動けば良い」って考え方もあるんですが・・・・・。
どないすんねん、これ、ってカンジです。

平たく言うと、貴方の予想通り、

hyotei(ginou) <- これが要らない
eva = hyotei(ginou)
hyotei(kangae) <- これが要らない
eva2 = hyotei (kangae)
hyotei(chishiki) <- これが要らない
eva3= hyotei (chishiki)

です。
(期せずしてなった)ローカル関数には不幸な事に出力関数printが入っています。
つまり例えば、

hyotei(ginou) # ここで出力される
eva = hyotei(ginou) # ついでにここでも出力される

んで、「二回出力されてる」んですね。全く同じ結果が二回印字されるのはそのせいです。
    • good
    • 0
この回答へのお礼

ありがとうございます。
おっしゃる通り、まだグローバル関数なるものを習っておらず、とりあえず知ってる知識だけで書きました。
いらないところを消したら動きました。。。が、
例えば出力はまったくせずに、returnで帰ってくる数値だけを参照して計算したりするばあいはどうしたらいいでしょうか。
たとえば
eva=3 のとき
print(hyotei(ginou)+5)
だと、計算結果の8以外に、A 100.0 %という出力結果が出てしまいます。

お礼日時:2018/09/14 19:54

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