読者です 読者をやめる 読者になる 読者になる

Python3.4のSingle-dispatchでpprintをパワーアップさせてみた!!

前置き

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

https://github.com/doloopwhile/single-dispatch-pprint

以下は、自作の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)

レガシーコード改善ガイド (Object Oriented SELECTION)

  • 作者: マイケル・C・フェザーズ,ウルシステムズ株式会社,平澤章,越智典子,稲葉信之,田村友彦,小堀真義
  • 出版社/メーカー: 翔泳社
  • 発売日: 2009/07/14
  • メディア: 大型本
  • 購入: 45人 クリック: 673回
  • この商品を含むブログ (144件) を見る

広告を非表示にする