Pythonループ・関数のよくある間違い

レッスンの本文で注意している点を、つまずきの側から51件ぶん並べ直しました。書いた覚えのある形が見つかったら、 そのままレッスンに戻って前後を読めます。

total = 0 の書き忘れ

用意していない名前にいきなり足そうとすると NameError になります。ループの前に必ず初期値を置きます。

forで合計で詳しく読む

return をループの中に書いてしまう

return total がインデントの内側にあると、1 周目で関数が終わってしまい、最初の 1 件だけが返ります。return はループの外、for と同じ深さより手前に置きます。

forで合計で詳しく読む

リストそのものを足してしまう

total = total + prices と書くと、数値とリストを足すことになり TypeError です。足すのは取り出した 1 件の price です。

forで合計で詳しく読む

whileで繰り返す

レッスンを読む

カウンタを進め忘れる

i = i + 1 を書き忘れると、同じ 1 件を永久に読み続けます。手元で試すときは、止まらなくなったら Ctrl + C で強制終了できます。

whileで繰り返すで詳しく読む

i = i + 1break の前に置いてしまう

位置そのものは動きますが、終了items に入れてしまう順番になっていないか、必ず読み返します。取り込むのは 終了 ではない行だけです。

whileで繰り返すで詳しく読む

while の条件を i <= len(inputs) にしてしまう

最後の 1 件を読んだあと、存在しない位置を読もうとして IndexError になります。件数が 3 なら読める位置は 0 と 1 と 2 までです。

whileで繰り返すで詳しく読む

終わりの値を 1 つ足し忘れる

range(1, last_day, step) と書くと最終日が出ません。last_day まで含めたいなら last_day + 1 です。

rangeとstepで詳しく読む

数値と文字列をそのまま足す

day + "日目"TypeError になります。str(day) で文字列に変えてからつなぎます。

rangeとstepで詳しく読む

step0 を渡してしまう

range の刻み幅に 0 は使えず、ValueError になります。刻み幅は必ず 0 以外です。

rangeとstepで詳しく読む

breakとcontinue

レッスンを読む

breakcontinue を取り違える

0 円を飛ばすつもりで break を書くと、最初の 0 円で集計が止まってしまいます。飛ばしたいのか終わりたいのか、書く前に決めます。

breakとcontinueで詳しく読む

continue の下に処理を書いて実行されると思い込む

continue より下の行は、その周では絶対に動きません。「書いたのに動かない」の原因になりがちです。

breakとcontinueで詳しく読む

whilecontinue を使ってカウンタを飛ばす

while の中で continue すると、カウンタを進める行を飛ばしてしまい無限ループになります。whilecontinue の組み合わせは特に慎重に扱います。

breakとcontinueで詳しく読む

enumerateで番号付け

レッスンを読む

毎周のうしろに改行を足す

result = result + str(i) + ". " + name + "\n" と書くと、最後の行のうしろにも改行が残ります。改行は行の 手前 に足すと、この問題が起きません。

enumerateで番号付けで詳しく読む

zipで組み合わせ

レッスンを読む

zip に渡し忘れる

for name, price in names: と書くと、品名 1 文字ずつを 2 つに分けようとして ValueError になります。組にするには zip が要ります。

zipで組み合わせで詳しく読む

長さのずれに気づかない

zip は短いほうで止まり、余った分を黙って捨てます。件数が合うことを前提にするなら、len を比べて確かめる処理を別途書きます。

zipで組み合わせで詳しく読む

入れ子ループ

レッスンを読む

行の入れ物を初期化する位置を間違える

line = "" を外側のループより前に書くと、すべての行がつながってしまいます。行ごとにリセットする必要があります。

入れ子ループで詳しく読む

内側と外側で同じ変数名を使う

内側でも i を使うと、外側の i が上書きされて表が崩れます。外側は i、内側は j のように分けます。

入れ子ループで詳しく読む

break が外側まで効くと思い込む

breakcontinue は、いちばん内側のループ 1 つにしか効きません。内側で break しても、外側は次の周に進みます。

入れ子ループで詳しく読む

つくる:何件でも記録

レッスンを読む

金額とカテゴリを文字列に変え忘れる

record["price"] は数値なので、str を挟まないと TypeError です。record["category"] は最初から文字列なのでそのままつなげます。

つくる:何件でも記録で詳しく読む

空のときの分岐を書き忘れる

記録が 0 件でもループは静かに 0 周で終わるため、エラーは出ません。記録がありません の行が抜けたまま気づかない、というのがありがちです。

つくる:何件でも記録で詳しく読む

関数を定義する

レッスンを読む

コロンと字下げを忘れる

def greet_user(name) とコロンを書かないと SyntaxError です。字下げがないと IndentationError になります。字下げは半角スペース 4 つに揃えます。

関数を定義するで詳しく読む

呼び出しでかっこを付け忘れる

greet_user とだけ書くと、関数そのものを指すだけで実行されません。greet_user("たろう") とかっこを付けて初めて動きます。

関数を定義するで詳しく読む

return を書かずに print で済ませる

画面には出ますが、戻り値は None になります。採点は戻り値を見るので、必ず return で返します。

関数を定義するで詳しく読む

引数と戻り値

レッスンを読む

引数の順番を間違える

位置引数は前から順に入ります。split(people, total) のように順を取り違えると、エラーは出ないのに答えだけが狂います。いちばん見つけにくい種類のバグです。

引数と戻り値で詳しく読む

引数の数が合わない

add_tax() のように渡し忘れると TypeError になり、missing 1 required positional argument と教えてくれます。多すぎても同じく TypeError です。

引数と戻り値で詳しく読む

/// を取り違える

price * 110 / 100 は小数の 132.0 になります。132 とは別の値なので、テストは落ちます。整数が欲しいときは // です。

引数と戻り値で詳しく読む

デフォルト引数

レッスンを読む

リストや辞書を既定値にする

呼び出しをまたいで同じものが使い回されます。None を既定値にして関数の中で作り直します。

デフォルト引数で詳しく読む

境界を取り違える

>= にすると 3000 円ちょうどでもオーバー扱いになります。>>= のどちらが仕様かを確かめてから書きます。

デフォルト引数で詳しく読む

キーワード引数

レッスンを読む

引数名を間違える

format_record("りんご", 120, categoly="食費") のように綴りを間違えると TypeError になり、unexpected keyword argument と出ます。定義側の綴りを確認します。

キーワード引数で詳しく読む

同じ引数を二重に渡す

format_record("りんご", 120, "食費", category="日用品") は、category に位置とキーワードの両方から値が来るので TypeError です。どちらか片方にします。

キーワード引数で詳しく読む

str を忘れて数値を連結する

name + " " + priceTypeError です。金額は数値なので、str(price) で文字列にしてからつなぎます。第 2 章でやった変換がここでも要ります。

キーワード引数で詳しく読む

複数の戻り値

レッスンを読む

return を 2 行書く

return total の次の行に return average と書いても、2 行目には決して届きません。return は関数を終わらせるので、1 つの return にカンマで並べます。

複数の戻り値で詳しく読む

受け取る変数の数が合わない

total, average, count = total_and_average(prices)ValueError です。not enough values to unpack と出ます。

複数の戻り値で詳しく読む

引数の順番を逆にする

divmod(people, total) と書くと divmod(3, 1000) になり、商が 0 で余りが 3 という意味の分からない答えが返ります。エラーが出ないぶん厄介です。

divmodで詳しく読む

タプルのまま返してしまう

この環境の判定はリスト形式なので、return divmod(total, people) では通りません。q, r = divmod(...) で受けてから [q, r] にします。

divmodで詳しく読む

変数のスコープ

レッスンを読む

関数の外の変数を直接書き換えようとする

UnboundLocalError になります。global で押し切らず、引数と戻り値の形に直します。

変数のスコープで詳しく読む

戻り値を受け取り忘れる

add_record(records, "りんご", 120, "食費") とだけ書いて records = を付けないと、新しいリストは捨てられ、何も増えません。エラーが出ないぶん気づきにくい間違いです。

変数のスコープで詳しく読む

キーの名前を間違える

キーは namepricecategory の 3 つです。namae などと書くと、あとで取り出すときに落ちます。

変数のスコープで詳しく読む

lambdareturn を書く

lambda r: return r["price"]SyntaxError です。lambda は式なので、return は書きません。

lambda関数で詳しく読む

key に呼び出した結果を渡す

key=lambda r: r["price"]() のようにかっこを付けると、金額を関数として呼ぼうとして TypeError になります。渡すのは関数そのものです。

lambda関数で詳しく読む

sortsorted を取り違える

records.sort() は元のリストを並べ替えて None を返します。新しいリストが欲しいときは sorted です。戻り値が None になっていたら、まずここを疑います。

lambda関数で詳しく読む

つくる:関数に分割

レッスンを読む

over を文字列にする

"オーバー" のような文字列ではなく、TrueFalse の真偽値を入れます。判定結果は真偽値で返し、言葉にするのは表示側の仕事です。

つくる:関数に分割で詳しく読む