Pythonを勉強していて「こういう書き方があったのか」と思ったことを3つ

プログラミングを勉強していると
「こういう時はこんな書き方ができるのか」
とか
「この書き方を知っていればあの時のコードもっとうまく書けたな」
と感じることがあると思います。
この記事では私がPythonを勉強していてそう感じたことを3つ紹介したいと思います。
(常識だよ!ってことばかりだったらすみません)

1.複数の変数を比較する条件式の書き方

例えば3つの変数a, b, cがすべてNoneであれば真となる条件式は通常

if a is None and b is None and c is None:
    print u'すべてNone'

のように書きますが次のように書くこともできます。

if a is b is c is None:
    print u'すべてNone'

これはPythonの比較演算子の特徴を利用した書き方です。
Pythonでは変数aが1より大きく5より小さいという条件式を書く場合に下のように続けて書くことができます。

if 1 < a < 5:
    print u'aは1から5の間'

これを一般化すると「Pythonの比較演算子には右結合・左結合といった概念がなく常に両隣の値を比較し、その論理積が式の値となる」と考えることができます。そのため

1 < a < 5
# 下のように解釈される
1 < a and a < 5

と同様に

a is b is c is None
# 下に等しい
a is b and b is c and c is None

となり

a is None and b is None and c is None

と同値であることがわかります。

ただしこの書き方は否定が入るととたんに分かりづらくなってしまいます。
変数aとbがNoneでcがNoneではないという式は

a is b is None is not c

と書くことができますが読みづらいので効果的に使えるのは「すべての変数が同じ値である」などいくつかの条件の場合に限られるかと思います。

2.in演算子を使って変数が定義されているかどうかを確認する書き方

Pythonでは未定義の変数を参照しようとすると'NameError'例外となるため変数が定義されているかどうかを確認するにはこの例外をチェックするのが手っ取り早い方法です。
例えば変数hogeが定義されていればそのまま、定義されていなければ1を代入する場合は下のようになります。

try:
    hoge = hoge
except NameError:
    hoge = 1

ただ、変数が定義済みかどうかを確認するためだけに4行も使うのはちょっと大袈裟といいますかもっと簡潔に書きたいところです。
そこで使うのがin演算子と、定義されている変数の辞書を返す'locals()'、'globals()'関数です。
'locals()'関数は現在のスコープで定義されている変数を{'変数名': '値'}の辞書で返し'globals()'はグローバル変数の辞書を返します。
これを使って上のコードを書き直すと次のようになります。

hoge = hoge if 'hoge' in locals() else 1

参考:python - How do I check if a variable exists? - Stack Overflow

3.関数の戻り値を代入する際にタプルパック、シーケンスアンパックをつかう書き方

タプルパックというのは','で繋がれた複数の値を評価すると暗黙のうちにタプルとして評価されるというものです。

>>> hoge = 1, 2, 3
>>> hoge
(1, 2, 3)

シーケンスアンパックは','で繋がれた複数の変数に対してタプル・リスト・文字列などiterableな値を代入すると要素数が一致する場合自動的に展開されて代入されるというものです。

>>> a, b, c = (3, 5, 7)
>>> a
3
>>> b
5
>>> c
7
>>> d, e, f = 'ABC'
>>> d
'A'
>>> e
'B'
>>> f
'C'

両者の複合技として下のような代入の仕方が可能になっています。

>>> a, b, c = 1, 'A', 5
>>> a
1
>>> b
'A'
>>> c
5

これを関数の戻り値を代入する際に使うと複数の値を戻したい場合に簡潔に書くことができます。

def test():
    return 1, 3, 5

a, b, c = test()

print a  # 1
print b  # 3
print c  # 5

辞書やリストを戻しそこから個別の値を取り出して使用する方法もありますが、辞書やリストにするほど結び付きが強くない複数の値を戻す際に便利ではないでしょうか。

import math

def mean(*args):
    '引数の相加平均と相乗平均を求める'
    add = 0.0
    multi = 1.0
    L = len(args)
    for v in args:
        add += v
        multi *= v

    arith = add / L
    geo = math.pow(multi, 1.0 / L)
    
    return arith, geo

arith, geo = mean(5, 20)

print arith # 12.5
print geo   # 10.0

参考:タプル(3) - バリケンのPython日記 - pythonグループ

以上、私がPythonを勉強していて「こういう書き方があったのか」と思ったことでした。
実際はもっとたくさんあったと思うのですがすぐに思いつくのがこの3つだったので今回は3つにしました。