前置き
Python3.4のSingle-dispatchで遊んでみた - Python Advent Calendar 2013 — hirokiky's blog
読んだ瞬間、脳細胞に衝撃が!
「これはpprintのための新機能だ!」
「あの長いPrettyPrinter._formatがsingledispatchでプリチーに書ける!」
「自作クラスをpprintできるようになったに違いない!」
はやる心を抑え、3.4.0b1をダウンロード し、Lib/pprint.py をgvimで開くと、そこには!?
作ってみた
というわけで、 Single-Dispatch を使ったpprintを実装してみました。
doloopwhile / single-dispatch-pprint
Re-implementation of 'pprint' in Python Standard Library using singledispatch
以下は、自作のSpamクラスをPretty Printする例です。
spprint.format_instance
がシングルディスパッチ関数であり、
自作クラスを登録できます。
import spprint
class Spam:
def __init__(self, count, side_dish):
self.count = count
self.side_dish = side_dish
def __repr__(self):
return "<Spam {}and {}>".format('spam ' * self.count, self.side_dish)
@spprint.format_instance.register(Spam)
def format_spam(obj, context):
w = context.stream.write
w("<Spam \n")
for _ in range(obj.count):
w(' ' * (context.indent + context.indent_per_level))
w('spam\n')
w(' ' * (context.indent + context.indent_per_level))
w('and {}>'.format(obj.side_dish))
spprint.pprint([Spam(2, 'Egg'), Spam(7, 'Ham')], width=40)
Spam(2, 'Egg')
は1行の幅(ここでは40文字)に収まるので Spam.__repr__
を使って1行で表示されますが、 収まらない Spam(7, 'Ham')
はformat_spamを使って複数行で表示されます。
spprint
ではPrettyPrinter._formatを再実装しています。
format_instanceに登録されているlistやdictなどは専用の関数をdispatchし、
そうでなければ __repr__
を使います。
singledispatchに無関係なぶぶんは pprint
のものをそのまま使用しています。
ちなみに
spprintでは、Pythonに付属するpprint用のテストを利用して、テスト駆動開発をしてみました。
レガシーコード改善ガイド (Object Oriented SELECTION)にしたがって、
PrettyPrinter.formatの内容をスプラウトクラスに切り分ける
→テストする
→formatの中身をスプラウトメソッドに分ける
→テストする
→さらにスプラウトメソッドに分ける
→テストする
→(以下繰り返し)
という手順でやったので、スムーズに作業することができました。
レガシーコード改善ガイド (Object Oriented SELECTION)はマジオススメです(超今更)。
レガシーコード改善ガイド (Object Oriented SELECTION)
- 作者: マイケル・C・フェザーズ,ウルシステムズ株式会社,平澤章,越智典子,稲葉信之,田村友彦,小堀真義
- 出版社/メーカー: 翔泳社
- 発売日: 2009/07/14
- メディア: 大型本
- 購入: 45人 クリック: 673回
- この商品を含むブログ (144件) を見る