2012-04-01 3 views
3

Pythonで基本的なプログラムを書いています。ユーザーに5つのテストスコアを入力するよう促しています。プログラムは、各テストスコアを成績ポイント(すなわち、4.0,3.0,2.0 ...)に変換し、その後、これらの数値の平均をとる。私は、各テストを割り当てたforループに入力された変数をリスト形式で変更する方法

は独自の変数を獲得し、次のように私はループのためにそれらを供給しています:

for num in [score1, score2, score3, score4, score5]: 
    if num >= 90 
     print('Your test score is a 4.0) 
    elif num < 90 and >= 80 
    . 
    . 
    and so on for each grade point. 

を今、これは各テストのスコアがグレードと同等であるものを表示するための細かいんポイントワイズ。しかし、関数の後半では、これらの成績ポイント値のそれぞれの平均を計算する必要があります。だから、私は実際にその時点でforループを通過した特定の変数に等級点の値を代入したいと思います。したがって、score1がforループに渡され、適切な成績ポイントが決定されると、実際にその成績ポイントをscore1に割り当て、その後score2に割り当てることができますか?

質問が明確になることを願っています。あなたが渡されているリストの一部であるなら、forループを通って渡された変数を再定義することができないので、Pythonがこのような機能を持たないのは馬鹿げているようです。

+1

* "このような機能を備えていないのは愚かなようです。なぜなら、そうでなければ、forループで渡された変数を再定義することができないからです" - これがほとんどのプログラミング言語のしくみです。この機能を有効にすることは、コードを鈍らせる副作用と呼ばれるものを作成するため、悪いことになります。 – ninjagecko

答えて

8

"もしそうでなければ、それが渡されているリストの一部であるなら、forループを通して渡された変数を再定義することができないので、Pythonはこの種の機能を持たないと思われるでしょう" - これがほとんどのプログラミング言語のしくみです。この機能を有効にすることは、コードを鈍らせる副作用と呼ばれるものを作成するため、悪いことになります。

あなたは変数名からデータを維持する必要がありますので、また、これは一般的なプログラミングの落とし穴です:http://nedbatchelder.com/blog/201112/keep_data_out_of_your_variable_names.html(同様の質問の、特にリストを参照してください。あなたは、変数名を扱っていない場合でも、あなたは少なくともしようとしています変数名前空間を扱う)。救済策は「1つ上のレベル」で作業することです:この場合はリストまたはセットです。これがあなたの元の質問が妥当でない理由です。 (のpythonの一部のバージョンは、あなたがlocals()辞書をハックできるようになるが、これはサポートされていないと文書化されていない行動と非常に悪いスタイルです。)


あなたはしかし、そうのような副作用を使用するのpythonを強制することができ

scores = [99.1, 78.3, etc.] 
for i,score in enumerate(scores): 
    scores[i] = int(score) 

上記の数値は、scores配列の数値を丸めます。あなたがスコアにやりたい多くのものを持っている場合は

scores = [...] 
roundedScores = [int(score) for score in scores] 

:(あなたは要素の数百万で作業している場合を除く)ただし、これを行うには正しい方法はそうのようなscores配列を再作成することです:

scores = [..., ..., ...] 

def processScores(scores): 
    '''Grades on a curve, where top score = 100%''' 
    theTopScore = max(scores) 

    def processScore(score, topScore): 
     return 100-topScore+score 

    newScores = [processScore(s,theTopScore) for s in scores] 
    return newScores 

追記:あなたはフロートの計算をやっている場合は、あなたがfrom __future__ import divisionかのpython3を使用するか、明示的にfloat(...)にキャストする必要があります。


実際に渡される内容を変更したい場合は、変更可能なオブジェクトを渡すことができます。あなたが渡している数字は、不変オブジェクトのインスタンスであるが、たとえば、あなたが持っていた:

class Score(object): 
    def __init__(self, points): 
     self.points = points 
    def __repr__(self): 
     return 'Score({})'.format(self.points) 

scores = [Score(i) for i in [99.1, 78.3, ...]] 
for s in scores: 
    s.points += 5 # adds 5 points to each score 

これはまだ非機能物事を行う方法、およびすべての問題の副作用することが起こりやすくなり原因。

+0

すべてのアドバイスをいただければ幸いです。私は、コードを鈍くすることに関してあなたが言っていることを得ていると思います。興味深いことに、私はそれが予期せぬエラーを引き起こす可能性があることを知ることができますが、私は正確な理由を聞くことに興味があります。 一方、実際には変数を変更したり、カーブのようなグローバルな変更を引き起こす代わりに、変数を再定義することを検討しています。あなたの投稿は、行う方法を概説する素晴らしい仕事です。ありがとう –

+1

@DustinBurns:副作用が制御された副作用でなければ、コードをモジュール化する能力を失うので、副作用が予期しないエラーを引き起こします。副作用のある関数を呼び出すことは、値を単に返すだけではないため、悪いことです。したがって、副作用を伴う関数を簡単にテストすることはできません。副作用が2回ある関数を呼び出すと、同じ値が返されないことがあります。出力は関数外に存在するデータに依存することがあります。それは大量のコードを混乱させます。 – ninjagecko

+0

申し訳ありませんが、それはきれいにクリアクール:)ありがとう –

1

問題は、あなたがこの書くときということです:何が起こっているのか

for num in [score1, score2, score3, score4, score5]: 

をあなたが起動時にスコア5を通じてSCORE1の値によって定義されている5つの要素があり、リストを作成しているということです反復する。これらの要素のいずれかを変更しても、元の変数は変更されません。これは、これらの値のコピーを含むリストを作成したためです。

次のスクリプトを実行した場合:

score1 = 2 
score2 = 3 

for num in [score1, score2]: 
    num = 1 

for num in [score1, score2]: 
    print(num) 

あなたは、実際の変数のコピーを含むリスト内の各値を変更すると、実際に元の変数の値を変更しないことがわかります。これをよりよく理解するには、「参照渡し」と「値渡し」の違いを調べることを検討してください。

この特定の問題については、変更可能な変数をリスト内に配置し、それらの変数のコピーを含むリストではなく、そのリストを反復することをおすすめします。私は、これはあなたがやりたいかもしれないと思う

+0

うん。私は、forループが開始し、それらの特定の値を呼び出すとき、forループの外側からそれらの値を引き出すことになるので、内部の変更はループを再初期化するときに効果がないことを理解します。この理由から、ループの外でリストを定義するほうが簡単なので、値を送信する前にループ外のリストを変更することができます。私は不思議ですが、リストの内容を変更し、それらの新しい値をコードのメイン関数/本体に戻します。それは私が探しているものではありませんが、あなたがそれを行うことができるかどうか疑問に思っています –

2
# Take the list of grade as input, assume list is not empty 
def convertGrade(myGrades): 
    myResult = [] # List that store the new grade 
    for grade in myGrades: 
     gpa = (grade/20) -1 
     # Depending on how many deciaml you want 
     gpa = round(gpa, 1) 
     myResult.append(gpa) 
    return myResult 

# The list of grades, can be more than 5 if you want to 
grades = [88.3, 93.6, 50.2, 70.2, 80.5] 
convertedGrades = convertGrade(grades) 
print(convertedGrades) 

total = 0 
# If you want the average of them 
for grade in convertedGrades: 
    total += grade # add each grade into the total 

average = total/len(convertedGrades) 
print('Average GPA is:', average) 

は、物事のこの種のは非常に簡単ですので、あなたは、PythonがGPAコンバータ機能が付属していなければならないわけ場合Pythonは、私は知らないあなたはそれを自分で書くことを期待しますあなたは確かに簡単に書き込むことができます。整数だけが必要な場合(GPAには通常小数点が付いているのでわからない)、追加する前にint()を使用するか、0に丸めることができます。

出力:

[3.4, 3.7, 1.5, 2.5, 3.0] 
Average GPA is: 2.82 
+0

私はちょうどそのような変換をforループに直接置くことができるかどうか疑問に思っていました。別の変換。このオプションはうまくいきますが、私はforループを書くときに私の限界が何であったのか不思議に思っていました。ありがとうございました:) –

+0

私はこれを行う代わりに、上記のように平均をGPAに変換すると思います。だから、私が得点のリストの平均を取ったとき、私はただ平均を取る関数でそれをGPAに変換します。 –

+1

さて、どちらの方法でも動作します。時々、すべてを分解することは良い考えかもしれません。あなたの必要に応じて。 – George

1

まずルール:ないという名前の変数の束を使用しない、同様の項目の束を扱う - 作るものは何でも配列(リスト、セット、辞書を使いますほとんどの意味)。

二番目のルール:あなたは本当に宇宙押されていない限り、があなたの変数この方法を上書きしない - あなたは1つのラベル(変数名)は、2つの異なるもの(生のマークおよび/またはGPAのために目立たせるためにしようとしています)。これにより、デバッグが本当に面倒です。

def get_marks(): 
    marks = [] 
    while True: 
     inp = raw_input("Type in the next mark (just hit <Enter> to quit): ") 
     try: 
      marks.append(float(inp)) 
     except ValueError: 
      return marks 

def gpa(mark): 
    if mark >= 90.0: 
     return 4.0 
    elif mark >= 80.0: 
     return 3.0 
    elif mark >= 70.0: 
     return 2.0 
    elif mark >= 60.0: 
     return 1.0 
    else: 
     return 0.0 

def average(ls): 
    return sum(ls)/len(ls) 

def main(): 
    marks = get_marks() 
    grades = [gpa(mark) for mark in marks] 

    print("Average mark is {}".format(average(marks))) 
    print("Average grade is {}".format(average(grades))) 

if __name__=="__main__": 
    main() 
+0

私はお詫びします、私はこれで少し新しいです。アドバイスをいただきありがとうございます。私は興味があり、私は自分自身でそれを見てみるだろうが、あなたが平均(ls)を定義するとき、どこからその変数を引っ張っているのか。 lsは、あらかじめ定義されたリストのすべての値を意味しますか?もしそうなら、それは理にかなっています。再度、あなたの助けに感謝します! –

+0

ああ、待って、あなたがそこで何をしたのか分かります。後でmain関数をコールし、lsを定義した関数に入れて、関数にプッシュできる変数を制限しないようにしました。クール。 –

+0

2つの書かれた規則のsage助言のためのUpvote。 – otocan

関連する問題