とほほのPython入門 - 制御構文
- もし~ならば(if, else, elsif)
- ~のあいだ(while, else)
- ~のあいだ(for, in)
- ループを抜ける(break)
- ループを繰り返す(continue)
- 例外処理(try, except, else, finally, as, raise)
- with構文(with)
- アサーション文(assert)
- パス文(pass)
- デリート文(del)
- exec文(exec)
- マッチ文(match)
- コルーチン(async, await)
もし~ならば(if, else, elsif)
if expr1:
suite1...
[elif expr2:
suite2...]*
[else:
suite3...]
if は「もし」を意味します。式 expr1 が真であれば、インデントされたブロック suite1 を実行します。下記の例では、num の値が 10より大きければ BIG を3回表示します。
num = 12
if num > 10:
print("BIG")
print("BIG")
print("BIG")
else は「さもなくば」を意味します。下記の例では、num が 10より大きければ BIG を、さもなくば SMALL を表示します。
num = 12
if num > 10:
print("BIG")
else:
print("SMALL")
elif は「さもなくばもし」を意味します。下記の例では、num が 10より大きければ BIG を、10と等しければ NORMAL を、さもなくば SMALL を表示します。
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 の値を表示します。
n = 0
while n < 10:
print(n)
n += 1
else がある場合は、ループの最後に else節を実行します。
n = 0
while n < 10:
print(n)
n += 1
else:
print('END')
~のあいだ(for, in)
for var in expr:
suite1...
[else:
suite2...]
for はリスト、タプルの各要素、辞書のキー、文字列の各文字、ファイルの各行などに対して処理 suite1 を繰り返します。
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 を実行します。
for n in [1, 2, 3]:
print(n)
else:
print('END')
処理を10回繰り返したい場合は range() を用います。
for n in range(10):
print(n)
ループを抜ける(break)
break は最も内側の while, for などのループ処理を抜けます。下記の例では n が 5の時に forループを抜けます。
for n in range(10):
if n == 5:
break
print(n) # 0, 1, 2, 3, 4
ループを繰り返す(continue)
continue は最も内側の while, for などのループ処理を繰り返します。下記の例では n が 5の時に forループの先頭に戻ります。
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)などの例外を扱います。
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 は例外情報を変数として受け取ります。
try:
xxx
except SystemError as e:
print("SystemError")
print(e)
raise は例外を発生させます。下記の例は、直近に発生した例外を再発生させます。例外が発生していない場合は TypeError例外を発生させます。
try:
...
except:
raise
下記の例は、'Error message' を引数に SystemError のコンストラクタを呼び出し、生成したインスタンスを引数に例外を発生させます。
try:
raise SystemError('Error message')
except SystemError as e:
print("SystemError")
print(e)
下記の例では自作した例外に引数を与え、生成したインスタンスを引数に例外を発生させています。
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)
例外処理の中で例外を発生させるには、次のパターンがあります。
# 元の例外をそのまま投げる 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() が自動的に呼び出されます。
# 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 になります。
f = func() assert f == 5 # f の値が期待通り 5になっていることを確認する
assert expression は、下記と等価です。
if __debug__:
if not expression: raise AssertionError
assert expression1, expression2 は、下記と等価です。
if __debug__:
if not expression1: raise AssertionError(expression2)
パス文(pass)
pass は何もしない文です。中身の無い関数やクラスを作成する際に使用されます。
def myfunc():
pass
class MyClass:
pass
デリート文(del)
del はオブジェクトを削除します。
x = 5 y = [1, 2, 3] z = MyClass() del x, y, z
exec文(exec)
exec文(exec)は、引数の文字列を Python のスクリプトとして実行します。
exec(statements [, global [, local]])
サンプルを下記に示します。
exec("print('Hello')")
global と local には、グローバル変数、ローカル変数を辞書形式で渡します。ローカル変数を省略した場合は、global が両方に適用されます。
exec("print(global_x, local_y)", {'global_x': 100}, {'local_y': 200})
マッチ文(match)
Python 3.10 で追加された機能で、他言語の switch case に相当します。マッチしなかった場合は case _ が実行されます。
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のサイズを求めるというタスクを並列実行することができます。
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() が非推奨となっているのでこちらを使用するのがよさそうです。
def main():
asyncio.run(main())