とほほのPython入門 - 制御構文

トップ > Python入門 > 制御構文

目次

もし~ならば(if, else, elsif)

文法
if expr1:
    suite1...
[elif expr2:
    suite2...]*
[else:
    suite3...]

if は「もし」を意味します。式 expr1 が真であれば、インデントされたブロック suite1 を実行します。下記の例では、num の値が 10より大きければ BIG を3回表示します。

Python
num = 12
if num > 10:
    print("BIG")
    print("BIG")
    print("BIG")

else は「さもなくば」を意味します。下記の例では、num が 10より大きければ BIG を、さもなくば SMALL を表示します。

Python
num = 12
if num > 10:
    print("BIG")
else:
    print("SMALL")

elif は「さもなくばもし」を意味します。下記の例では、num が 10より大きければ BIG を、10と等しければ NORMAL を、さもなくば SMALL を表示します。

Python
num = 12
if num > 10:
    print("BIG")
elif num == 10:
    print("NORMAL")
else:
    print("SMALL")

if文では、False、数値の 0 や 0.0、空文字("")、空リスト([])、空タプル(())、空辞書({})などを偽とみなし、それ以外を真とみなします。

~のあいだ(while, else)

文法
while expr:
    suite1...
[else:
    suite2...]

while は「~のあいだ」を意味します。下記の例では、n の値が 10よりも小さい間 n の値を表示します。

Python
n = 0
while n < 10:
    print(n)
    n += 1

else がある場合は、ループの最後に else節を実行します。

Python
n = 0
while n < 10:
    print(n)
    n += 1
else:
    print('END')

~のあいだ(for, in)

文法
for var in expr:
    suite1...
[else:
    suite2...]

for はリスト、タプルの各要素、辞書のキー、文字列の各文字、ファイルの各行などに対して処理 suite1 を繰り返します。

Python
for n in [1, 2, 3]:          # 配列
    print(n)                 #=> 1, 2, 3

for n in (1, 2, 3):          # タプル
    print(n)                 #=> 1, 2, 3

for c in "ABC":              # 文字列
    print(c)                 #=> A, B, C

for k in {'one': 1, 'two': 2, 'three': 3}:   # 辞書
    print(k)                                 #=> one, two, three

for line in open("sample.txt"):              # ファイルの中身
    print(line)                              # 1行ずつ表示

else がある場合は、ループの最後に else 節 suite2 を実行します。

Python
for n in [1, 2, 3]:
    print(n)
else:
    print('END')

処理を10回繰り返したい場合は range() を用います。

Python
for n in range(10):
    print(n)

ループを抜ける(break)

break は最も内側の while, for などのループ処理を抜けます。下記の例では n が 5の時に forループを抜けます。

Python
for n in range(10):
    if n == 5:
        break
    print(n)                 # 0, 1, 2, 3, 4

ループを繰り返す(continue)

continue は最も内側の while, for などのループ処理を繰り返します。下記の例では n が 5の時に forループの先頭に戻ります。

Python
for n in range(10):
    if n == 5:
        continue
    print(n)                 # 0, 1, 2, 3, 4, 6, 7, 8, 9

例外処理(try, except, else, finally, as, raise)

文法
try:
    suite1...
[except [expr [as identifier]]:
    suite2...]*
[else:
    suite3...]
[finally:
    suite4...]

try, except, else, finally は文法エラー(SyntaxError)などの例外を扱います。

Python
str = 'ABC'
try:
    c = str[5]                    # 5番目の文字が無いので、IndexError例外が発生します
except IOError:
    print('IOError')              # IOError例外の場合、このブロックが実行されます
except IndexError:
    print('IndexError')           # IndexError例外の場合、このブロックが実行されます
except:
    print('Unknown')              # 上記以外の例外の場合、このブロックが実行されます
else:
    print('Other')                # 例外が発生しなかった場合、このブロックが実行されます
finally:
    print('Finally')              # 常に、このブロックが実行されます

as は例外情報を変数として受け取ります。

Python
try:
    xxx
except SystemError as e:
    print("SystemError")
    print(e)

raise は例外を発生させます。下記の例は、直近に発生した例外を再発生させます。例外が発生していない場合は TypeError例外を発生させます。

Python
try:
    ...
except:
    raise

下記の例は、'Error message' を引数に SystemError のコンストラクタを呼び出し、生成したインスタンスを引数に例外を発生させます。

Python
try:
    raise SystemError('Error message')
except SystemError as e:
    print("SystemError")
    print(e)

下記の例では自作した例外に引数を与え、生成したインスタンスを引数に例外を発生させています。

Python
class MyError(Exception):
    def __init__(self, file, lineno):
        self.file = file
        self.lineno = lineno

try:
    raise MyError("test.txt", 1163)
except MyError as e:
    print("MyError")
    print(e.file)
    print(e.lineno)

例外処理の中で例外を発生させるには、次のパターンがあります。

Python
# 元の例外をそのまま投げる
except Exception as e:
    raise e

# 新たな例外を生成して投げる
except Exception:
    raise MyError()

# 元の例外情報をつけて、新たな例外を投げる
except Exception as e:
    raise MyError() from e

# 元の例外を無視して、新たな例外を投げる
except Exception:
    raise MyError() from None

with構文(with)

文法
with expression [as target] [, expression [as target]]... :
    suite...

with を用いると、withブロックが終了した際に、オブジェクトの終了処理が自動的に呼ばれます。例えば、open() で返却される file オブジェクトは、終了処理として、close() が自動的に呼び出されます。下記の例で、with を用いた書き方では、withブロックが終了した際に f.close() が自動的に呼び出されます。

Python
# withを用いない書き方
f = open("test.txt")
print(f.read())
f.close()

# withを用いた書き方1
with open("test.txt") as f:
    print(f.read())

# withを用いた書き方2
f = open("test.txt")
with f:
    print(f.read())

アサーション文(assert)

assert はテストの際に値が期待通りに設定されているかを確認するための仕組みです。__debug__ が True の時のみ動作し、式を評価して偽であれば、AssertionError例外を発生させます。python を -O オプション付きで起動することで、__debug__ の値は False になります。

Python
f = func()
assert f == 5              # f の値が期待通り 5になっていることを確認する

assert expression は、下記と等価です。

Python
if __debug__:
    if not expression: raise AssertionError

assert expression1, expression2 は、下記と等価です。

Python
if __debug__:
    if not expression1: raise AssertionError(expression2)

パス文(pass)

pass は何もしない文です。中身の無い関数やクラスを作成する際に使用されます。

Python
def myfunc():
    pass

class MyClass:
    pass

デリート文(del)

del はオブジェクトを削除します。

Python
x = 5
y = [1, 2, 3]
z = MyClass()
del x, y, z

exec文(exec)

exec文(exec)は、引数の文字列を Python のスクリプトとして実行します。

文法
exec(statements [, global [, local]])

サンプルを下記に示します。

Python
exec("print('Hello')")

globallocal には、グローバル変数、ローカル変数を辞書形式で渡します。ローカル変数を省略した場合は、global が両方に適用されます。

Python
exec("print(global_x, local_y)", {'global_x': 100}, {'local_y': 200})

マッチ文(match)

Python 3.10 で追加された機能で、他言語の switch case に相当します。マッチしなかった場合は case _ が実行されます。

Python 3.10~
c = 3
match c:
    case 1:
        print("One")
    case 2:
        print("Two")
    case 3:
        print("Three")
    case _:
        print("Other")

コルーチン(async, await)

Python 3.5 で導入された機能で、関数を非同期に呼び出すことが可能となります。getsize() というコルーチンをタスクリストとして複数呼び出すことにより、指定したURLのサイズを求めるというタスクを並列実行することができます。

Python 3.5~
import asyncio
import requests

urls = [
    "https://www.yahoo.co.jp",
    "https://www.google.com",
    "https://www.wikipedia.com"
]

async def getsize(url):
    print(f"getsize({url}) START")
    loop = asyncio.get_event_loop()
    r = await loop.run_in_executor(None, requests.get, url)
    print(f"getsize({url}) END {len(r.text)} bytes")

async def main():
    print('main() START')
    tasks = [asyncio.create_task(getsize(url)) for url in urls]
    await asyncio.gather(*tasks)
    print('main() END')

if __name__ == "__main__":
    loop = asyncio.get_event_loop()
    loop.run_until_complete(main())
実行結果
main() START
getsize(https://www.yahoo.co.jp) START                 # getsize()が並列に呼び出されている
getsize(https://www.google.com) START                  #    〃
getsize(https://www.wikipedia.com) START               #    〃
getsize(https://www.yahoo.co.jp) END 35804 bytes
getsize(https://www.google.com) END 15135 bytes
getsize(https://www.wikipedia.com) END 75189 bytes
main() END

Python 3.7 からは get_event_loop(), run_until_complete() の代わりに run() を使用できるようになりました。Python 3.10 からは get_event_loop() が非推奨となっているのでこちらを使用するのがよさそうです。

Python 3.7~
def main():
    asyncio.run(main())

Copyright(C) 2014-2022 杜甫々
初版:2014年12月30日、最終更新:2022年10月9日
http://www.tohoho-web.com/python/control.html