conditional expression の代替

なんか久々に紫藤さんのサイトを覗いたら、ちょっと面白い。

今まで、Python には三項演算子が無かったので、単に条件によって代入される値を変えるために

if predicate:
   value = then_value
else:
   value = else_value

と書くのは冗長なので、簡潔に、

value = predicate and then_value or else_value

書くことがしばしばありました。

Python プログラマはそういう書き方を嫌うんじゃないかなぁ。そのイディオムって一般的か?

しかしこの書き方には then_value が偽として認識されるものだと else_valuevalue に代入されるというバグが生じます。
これを回避するためには

(value,) = predicate and (then_value,) or (else_value,)

のように変数をタプルでくくる必要がありました。 この書き方ではバグは無いのですが、一見不必要なタプルを用いる必要があり、かなりいけていません。

タプル以前の段階でいけてないと思う。
あと、この説明はひどいと思う。

collection が defaultdict タイプを持つようになりました。このタイプは dict とほとんど同じであるが、 key が見つからない場合デフォルト値として空リストか 0 がセットされます。 どちらがセットされるかは、defaultdict(type) の引数で決まります。 type が list なら空リストを、 int なら 0 がセットされます。

まぁ、int を指定すれば 0、list を指定すれば空リストにはなるけど。defaultdict の引数は factory だからね。簡単な実装としてはこうか。

class defaultdict(dict):
    def __init__(self, default_factory = None, *args, **kwargs):
        dict.__init__(self, *args, **kwargs)
        self.default_factory = default_factory

    def __missing__(self, k):
        if self.default_factory is not None:
            self[k] = self.default_factory()
            return self[k]
        else:
            raise KeyError(k)

あー、でも __missing__ に関しては新発見。