リスト(数列)の差分のリストがほしかったんだけど、はまったのでメモ。
最初、↓こう書いた。
def difference(lis):
    d = reduce(lambda x, y: (x[0].append(y-x[1]), y), lis, ([],0))
    d[0].pop(0)
    return d[0]
a = range(10)
diff = difference(a)
print diff
2行目のx[0].append(y-x[1])で差分を蓄積していってそれを返している(3行目は余分な初期値との差分があるからそれを取り除いている)。
ところが実行するこうだ。
^o^ > python difference.py
Traceback (most recent call last):
  File "difference.py", line 9, in 
    diff = difference(a)
  File "difference.py", line 3, in difference
    d = reduce(lambda x, y: (x[0].append(y-x[1]), y), lis, ([],0))
  File "difference.py", line 3, in 
    d = reduce(lambda x, y: (x[0].append(y-x[1]), y), lis, ([],0))
AttributeError: 'NoneType' object has no attribute 'append'
‘NoneType’のオブジェクトは’append’なんて属性持ってないと。しばらく悩んだけど、原因はタイトルのとおり。
1回目のappendを呼び出したところでNoneが返ってくるので、2回目の呼び出しでは失敗する。
>>> a = range(5) >>> a [0, 1, 2, 3, 4] >>> type(a.append(5)) <type 'NoneType'>
結局、次のように書き換えたらうまくいったけど、関数がひとつ増えてしまった。
def difference2(lis):
    d = reduce(lambda x, y: (add_list(x[0], y-x[1]), y), lis, ([],0))
    d[0].pop(0)
    return d[0]
def add_list(lis, x):
    lis.append(x)
    return lis
a = range(10)
diff = difference2(a)
print diff
^o^ > python difference2.py [1, 1, 1, 1, 1, 1, 1, 1, 1]
RubyのArray#pushならselfを返してくれるから素直に書けるんだけどなあ。