Python2で競技プログラミングする時に知っておきたいtipsの,制御構造についての部分を分割しました.
Pythonのバージョンは2.7.5(Python3では,入出力などの仕様が大きく異なるので,他の記事を参照することをおすすめします).
条件分岐
条件式に変数を渡す
個人的にはあまり好きではないが,コード量削減のために,
while 1:
a = input()
if not a:
break
# ...
みたいに,if文,while文などの条件に変数を渡すことが多い気がする.
PythonでIf文に変数を入れたときの結果 - LIFE WITH PYTHON
型 | 結果 |
---|---|
int | 0ならFalse,それ以外ならTrue |
float | 0.0ならFalse,それ以外ならTrue |
str | ''(空文字)ならFalse,それ以外ならTrue |
list | []ならFalse,それ以外ならTrue |
tuple | ()ならFalse,それ以外ならTrue |
dict | {}ならFalse,それ以外ならTrue |
set | set()ならFalse,それ以外ならTrue |
None | False |
処理を途中で終了したい
入力の終わりを表す記号や,コーナーケースが入力された場合など,途中でスクリプトの実行を終了してしまった方が楽な場合がある.
このような場合は,quit()
またはsys.exit()
を使うとよい.
a = input()
if a == 0:
quit()
# ...
import sys
a = input()
if a == 0:
sys.exit()
# ...
繰り返し
range()とxrange()
2. 組み込み関数 — Python 2.7ja1 documentation
Pythonで「○○をn回行う」と言った単純な繰り返しを実装する場合は,
n = 5
for i in range(n):
print i
# 0
# 1
# 2
# 3
# 4
または,
n = 5
for i in xrange(n):
print i
# 0
# 1
# 2
# 3
# 4
のように書くのが一般的.
ここで,range(n)
,xrange(n)
は,それぞれ,0からnまでの整数を昇順に並べたlistオブジェクト,xrangeオブジェクトを返す.
xrangeオブジェクトは,遅延評価を用いることで,値が必要とされるときに取り出すことの出来るオブジェクト.
nが非常に多くなる場合,range(n)
ではリストを生成してからループを行うため,メモリ使用量が大きくなってしまうが,xrange(n)
ではそれが避けられる.
また,速度についても,一部の場合を除いてxrange()
の方が高速.
[python - Should you always favor xrange() over range()? - Stack Overflow]
(http://stackoverflow.com/questions/135041/should-you-always-favor-xrange-over-range)
また,(x)rangeでは,第2,第3引数を用いたり,reversed()
を用いることで,いろいろな範囲の表現ができる.
# range(start, stop)で,startからstop-1までの整数すべてを昇順に並べたリストを返す
print range(2, 6) # [2, 3, 4, 5]
# range(start, stop, step)で,startからstepおきに値を増やしていって得られる整数の内,stop-1までのすべてのものを昇順に並べたリストを返す
print range(5, 30, 5) # [5, 10, 15, 20, 25]
# reversed()でリストを逆順にできる
for i in reversed(range(5)):
print i
# 4
# 3
# 2
# 1
# 0
for文での変数の展開
for文で,
l = [1, 2, 3, 4, 5]
for e in l:
print e
1
2
3
4
5
のように,リストの各要素を展開できるが,これは,
l = [(0, 'a'), (1, 'b'), (2, 'c'), (3, 'd')]
for i, e in l:
print '#{0}: #{1}'.format(i, e)
0: a
1: b
2: c
3: d
のようにもできる.
enumerate
forループを回す際,リストのインデックスと値が同時に取得できるといい場合がある.
enumerate()
は,引数のリストに対して,インデックスとその値を持つイテレータを返す.
l = ['a', 'b', 'c', 'd']
for elem in enumerate(l):
print elem
# (0, 'a')
# (1, 'b')
# (2, 'c')
# (3, 'd')
# 上のコードは下記のコードと等価
for i in range(len(l)):
print (i, l[i])
for-else,while-else文
Pythonでは,for文,while文にelse節を加えることができる.
この際,else節は,ループ終了までに一度も内部でbreakされなかった場合のみ呼び出される.
a = [1, 2, 3, 4, 5]
b = [1, 2, 4, 5]
x = 3
def find_val(l, x):
for i in range(len(l)):
if l[i] == x:
print i
break
else:
print 'Not found...'
# 上のfind_val()と等価なコード
def find_val2(l, x):
flag = False
for i in range(len(l)):
if l[i] == x:
print i
flag = True
break
if not flag:
print 'Not found...'
find_val(a, x) # 2
find_val(b, x) # Not found...
「xを探せ.見つからなかった時は'hoge'を出力しろ」みたいな設問の際,フラグを持つ必要が無いため,非常に書きやすくて便利.
ただし,ループが多重になる場合はかえって見通しが悪くなるため,使わない方がよい.