制御フロー

これまで書いたプログラムは毎回同じように動作します。上から下へ、1行ずつ実行されます。単純なスクリプトではうまくいきますが、現実のプログラムは判断を下して処理を繰り返す必要があります。クイズは答えが正しいかをチェックし、ゲームはプレイヤーが勝つか負けるかまで実行し続ける必要があります。この章では、プログラムを分岐させて繰り返す方法を学びます。
比較
決断を下す前に、物事を比較する必要があります。比較演算子はTrueまたはFalseを返します。最初に正しく理解することが重要な点: =は値を代入し、==は2つの値が等しいかをチェックします。これを混同することは、初心者が最もよく犯す間違いの1つです。
5 > 3 # True
5 < 3 # False
5 == 5 # True (注: ダブルイコール; = は代入、== は比較)
5 != 3 # True ("以上でない")
5 >= 5 # True ("以上")
5 <= 4 # False ("以下")=と==の区別はほぼ誰もが初期段階でつまずきます。代入(=)は値を保存し、比較(==)は2つの値が同じかをチェックします。
文字列も比較できます。Pythonはそれらをアルファベット順に、文字ごとに比較します。文字列の章で詳しく説明します:
"apple" == "apple" # True
"apple" < "banana" # True (a は b の前)
"apple" == "Apple" # False (大文字小文字を区別)= は値を保存し、== は2つの値が等しいかをチェックします。疲れているときは今でも立ち止まってダブルチェックするので、つまずいても悪くありません。比較はTrueまたはFalseを渡し、文字列でも機能します。 条件を組み合わせる
and、or、notは比較を組み合わせます。andは両側が真である必要があります。orは少なくとも一方が真である必要があります。notは結果を反転させます。これらにより、「スコアは合格かつユーザーはアクティブ」のような現実世界の条件を表現できます。
age = 25
score = 88
age >= 18 and score >= 80 # True (両方とも真である必要があります)
age < 18 or score >= 80 # True (少なくとも1つは真である必要があります)
not age >= 18 # False (結果を反転させます)andは両側を必要とします。orは少なくとも一方を必要とします。notは反転させます。
and は両側が真を望み、or は少なくとも1つが真を望み、not は答えを反転させます。これはあなたが書く最も現実的な条件、例えば「スコアは合格andユーザーはアクティブ」をカバーします。Pythonは結果が分かった瞬間に確認を停止します。 真と偽
Pythonのすべての値には真偽の解釈があり、TrueまたはFalseでなくても。空の文字列、ゼロ、空のリスト、およびNoneはすべて条件でFalseのように振る舞います。その他すべてはTrueのように振る舞います。これはif results:がリストが非空であるかをチェックif len(results) > 0:と書くことなくチェックできることを意味します。
# これらはすべて条件で False のように振る舞います:
False, 0, 0.0, "", [], {}, (), None
# その他すべては True のように振る舞いますこれはif results:が「リストに何かあれば」という自然な言い方であり、if name:は文字列にコンテンツがあるかをチェックすることを意味します。
Falseとして数えられます: 0、""、[]、およびNone。その他すべてがTrueとして数えられます。そのためif results:は「リストに何かあれば」として読むので、len()は必要ありません。 if / elif / else
if文はその条件がTrueのときだけコードのブロックを実行します。elifは最初の条件が偽だった場合にチェックする条件を追加します。elseは条件にマッチしなかったすべてをキャッチします。Pythonは中括弧ではなく、インデントを使用して各ブロック内に何が属しているかを定義します。
score = 87
if score >= 90:
print("A grade")
elif score >= 80:
print("B grade")
elif score >= 70:
print("C grade")
else:
print("Below C")ルール:
ifは必須で常に最初に来ますelif(「else if」の短縮)はオプションで、必要な数だけ持つことができますelseはオプションで、マッチしなかったすべてを処理し、最後に来ます- Pythonはインデント(4つのスペース)を使用して、各ブロック内に何が属しているかをマークします。中括弧はありません
インデントはオプションでも美的でもありません。Pythonはそれを構造を定義するために使用します。インデントの一貫性がないことは構文エラーです。
if は条件が真のときそのブロックを実行し、elif はより多くのケースをチェックし、else は残りをキャッチします。最初のマッチだけが実行されます。私が初期段階でハマった点: インデントはPythonに各ブロックがどこで始まり、どこで終わるかを伝えるため、一貫性を保ちます。 ワンライン条件
単純な yes/no 代入の場合、Pythonは三項式と呼ばれるコンパクトなワンラインの形式を持っています: value_if_true if condition else value_if_false。ロジックが小さく、文のように読めるときにのみ使用します。
label = "pass" if score >= 50 else "fail"これは三項式です。文のように読みます。ロジックが小さいときに使用します。elifを含むものについては、完全なバージョンを書きます。
value_if_true if condition else value_if_false は1行で2つの値のいずれかを選択します。"pass" if score >= 50 else "fail"のようなきちんとした小さな選択に最適です。ロジックがそれを超えて成長した瞬間、通常のifブロックに戻ります。より良く読めるでしょう。 while ループ
whileループはその条件がTrueである限り、ブロックを繰り返します。ループが何回実行されるべきかが事前に分からない場合に使用します。例えば、有効な入力を待つか、ジョブが成功するまで再試行する場合。
lives = 3
while lives > 0:
print(f"Lives remaining: {lives}")
lives -= 1
print("Game over")whileは、ループが何回実行されるかが事前に分からない場合に最適です。既知の場合、またはコレクションを反復する場合、forはよりきれいです。
while は条件が真ままである限り、そのブロックを実行し続けます。有効な入力を待つのような、何ラウンド必要かが分からない場合にそれに頼ります。何かがループ内で終了に向かって移動することを確認します。そうしないと、永遠に実行され、1回以上犯した間違いです。 break と continue
breakはループを即座に終了し、残りの反復がいくつあっても構いません。continueは現在の反復の残りをスキップし、条件チェックに戻ります。両方とも、それらが内部にある最も内側のループにのみ影響します。
breakはループを即座に終了します:
target = 5
num = 0
while True:
num += 1
if num == target:
print(f"Found {target}")
break # ループを停止while True:とbreakは、終了条件が複雑であるか、ループボディの終わりで発生する必要がある場合、有効で一般的なパターンです。
continueは現在の反復の残りをスキップし、条件チェックに戻ります:
num = 0
while num < 10:
num += 1
if num % 2 == 0:
continue # 偶数をスキップ
print(num) # 奇数だけ印刷: 1, 3, 5, 7, 9break はループから即座にジャンプアウト、continue はこのラウンドの残りをスキップして条件チェックに戻ります。両方はそれらが直接内部にあるループだけに触れます。while True:とbreakは最初は奇妙に読みますが、何かが発生するまでループするための通常の方法です。 for ループ
forループはシーケンスを1つずつ、1つのアイテムずつ通り抜けます: リスト、文字列、数値の範囲。forの後で名前を付けた変数は順番に各アイテムを受け取ります。カウンターを管理したり、長さ自分でチェックしたりする必要はありません。
players = ["太郎", "花子", "一郎"]
for player in players:
print(f"Hello, {player}!")forループは文字列でも機能します(文字ごとに反復)し、その他のシーケンスタイプでも機能します。
for item in sequence は順番に各アイテムを歩き、カウンターや長さ自分に触れることはありません。リスト、文字列、範囲、たくさんのもので機能します。他の言語から来て、インデックスを管理しないことは最初は奇妙に感じました。その後、ギフトのように感じました。 range()
range()は数値のシーケンスを生成し、ループします。range(5)は0、1、2、3、4を与えます。開始、終了、およびステップ サイズを制御できます。ループが特定の回数実行される必要がある場合に使用します。
for i in range(5):
print(i) # 0, 1, 2, 3, 4range()には3つのフォームがあります:
| 呼び出し | 何を生成するか |
|---|---|
range(5) | 0, 1, 2, 3, 4 |
range(2, 6) | 2, 3, 4, 5 |
range(0, 10, 2) | 0, 2, 4, 6, 8 (ステップ 2) |
range(5, 0, -1) | 5, 4, 3, 2, 1 (カウント ダウン) |
range()はリストを作成しません。一度に1つの数値を生成します。これは非常に大きな範囲でも効率的です。
range(5) は0, 1, 2, 3, 4を与え、開始、停止、ステップを設定できます。ループが一定の回数実行される場合にそれに頼ります。リストを作成しません。各ラウンドに1つの数値を配ります。 enumerate()
enumerate()はループしながらインデックスと値の両方を与えるため、別々にカウンターを追跡する必要はありません。i, playerの部分は各反復に自動的に値のペアを受け取ります。
players = ["太郎", "花子", "一郎"]
for i, player in enumerate(players):
print(f"{i + 1}. {player}")
# 1. 太郎
# 2. 花子
# 3. 一郎i, player構文はアンパックと呼ばれます。Python は(index, value)ペアを2つの名前に自動的に分割します。
デフォルトではenumerate()は0で開始します。開始値を渡して変更します:
for i, player in enumerate(players, start=1):
print(f"{i}. {player}") # 1から開始enumerate() は位置と値を一緒に与えるため、同期を保つ個別カウンターはありません。i, playerの部分は一度に両方を引っ掛けます。誰かがリストを読むために番号を付けている場合、`start=1`を渡します。 ネストされたループ
別のループ内にループを配置できます。内部ループは外部ループの単一の反復ごとに完全に実行されます。これはグリッド、組み合わせ、または2つのレベルの構造を持つデータを処理する方法です。
rows = [1, 2, 3]
cols = ["A", "B"]
for row in rows:
for col in cols:
print(f"{col}{row}", end=" ")
print() # 各行の後の新しい行
# A1 B1
# A2 B2
# A3 B3ネストされたループ内のbreakとcontinueは最も内側のループにのみ影響します。
ループ else
Pythonループはbreakをヒットすることなくループが完了した場合にのみ実行されるelse句を持つことができます。それはよく使用されていませんが、「リストを検索し、何も見つからない場合はこれを実行する」という書き方で最もきれいです。
target = "田中"
names = ["太郎", "花子", "一郎"]
for name in names:
if name == target:
print(f"Found {target}")
break
else:
print(f"{target} not in list") # break が発生しなかったため実行されますbreakが実行されると、elseはスキップされます。ループがシーケンスを排出すると、elseが実行されます。これはニッチなパターンですが、フラグ変数よりきれいです。
breakなしで終了した場合にのみ実行されるelseを持つことができます。それはよく使用されていませんが、「このリストを検索して、何も一致しない場合はこれを実行する」と言う最も良い方法です。名前は少し誤解を招くため、短いコメントが役立ちます。 ソート
sorted()は新しいソート済みリストを返し、元のリストは変更されません。.sort()はリストをインプレイスでソートし、Noneを返します。key=引数を使用すると、生の値以外でソートできます。例えば、大文字小文字を区別しない名前をソートするか、スコア別のプレイヤータプルをソートしてください。
scores = [87, 42, 96, 55, 71]
ranked = sorted(scores) # [42, 55, 71, 87, 96] (新しいリスト)
scores.sort() # 元のリストをソートし、None を返します
scores.sort(reverse=True) # [96, 87, 71, 55, 42]両方ともkey=引数を受け入れます: 比較の前に各アイテムに適用される関数:
names = ["太郎", "花子", "一郎"]
sorted(names, key=str.lower) # 大文字小文字を区別しないソート
players = [("太郎", 87), ("花子", 96), ("一郎", 55)]
sorted(players, key=lambda p: p[1]) # スコア別でソートlambda p: p[1]はワンライン関数です: プレイヤーのタプルを取得してスコアを返します。ラムダはラムダと内包の章で完全に処理されます。
単純なケースの場合、sorted()を使用します。変更したいリストの場合は、.sort()を使用します。
sorted() は新しいソート済みリストを配ってオリジナルを単独で残し、.sort() はリスト自体を再配置してNoneを返します。`key=`を渡して、大文字小文字を区別しない名前のような生の値以外でソートします。疑わしい場合、sorted()に頼ります。安全なものです。 実際
スコアをループしてテータルを累積し、合格等級をカウント、サマリーを印刷します:
raw_scores = [87, 42, 96, 55, 71, 63]
total = 0
passing = 0
for score in raw_scores:
total += score
if score >= 60:
passing += 1
average = total / len(raw_scores)
print(f"Average: {average:.1f}")
print(f"Passing: {passing}/{len(raw_scores)}")
print(f"Top score: {sorted(raw_scores, reverse=True)[0]}")
