# Pythonで if の条件文の結果をブロック内で使いたい

# 動機(ストレス)

こんな感じのコードがあって、
あーでもないこーでもない考えた。

lines = ['abcdef', 'abc', 'def', 'ghi']
r1 = r'a(b)c'
r2 = r'd(e)f'

for line in lines:
  if re.match(r1, line):
    m = re.match(r1, line)
    print(m.group(1))
  elif re.match(r2, line):
    m = re.match(r2, line)
    print(m.group(1))
  else:
    print('not match')
  
  print('..')
  • 同じ match を2回ずつ呼ぶのが無駄
  • 2回ずつ出てくるので下記間違えそうで嫌

という点で嫌だが、
Python では if で代入ができない。

# こう書きたい1(Rubyの例):条件式の代入結果を使える

lines.each {|line|
  if m = line.match(/a(b)c/)
    puts m[1]
  elsif m = line.match(/d(e)f/)
    puts m[1]
  else
    puts 'not match'
  end
  
  puts '..'
}

# こう書きたい2(Rubyの例):直前のマッチは変数で取れる

lines.each {|line|
  if line =~ /a(b)c/
    puts $1
  elsif line =~ /d(e)f/
    puts $1
  else
    puts 'not match'
  end
  
  puts '..'
}

# 書き換え1:先にマッチする

for line in lines:
  m1 = re.match(r1, line)
  m2 = re.match(r2, line)

  if m1:
    print(m1.group(1))
  elif m2:
    print(m2.group(1))
  else:
    print('not match')
  
  print('..')
  • 通らないかもしれない r2 以降のマッチを毎回走らせるのが無駄

# 書き換え2:関数に出す

def f1(line):
  m = re.match(r1, line)
  if m:
    print(m.group(1))
    return
  m = re.match(r2, line)
  if m:
    print(m.group(1))
    return

  print('not match')
  
for line in lines:
  f1(line)
  print('..')
  • わざわざ関数使いたくなくて嫌
  • 行が増えて嫌
  • 同じ変数使い回すのも嫌
  • 変数を分けるのは分けるので間違えるから嫌

# 書き換え3:条件文で代入した風にする

def f1(line):
  for m in [m for m in [re.match(r1, line)] if m]:
    print(m.group(1))
    return
  for m in [m for m in [re.match(r2, line)] if m]:
    print(m.group(1))
    return

  print('not match')
  
for line in lines:
  f1(line)
  print('..')
  • 行は減ったけどそういう話ではない
  • あとで見て絶対わからないからダメ

    [ 📩 ご意見 ]