引越しのおしらせ
こちらのはてな日記の内容は、 http://www.gembook.org に 移転しました。
2012-11-29
引越しのおしらせ
こちらのはてな日記の内容は、 http://www.gembook.org に移転しました。
2012-10-24
Pythonで++i
この間、Pythonで変数のインクリメントないよね、って話がでた。こんなのだ。
i = 99
++i
print i
ちなみに、Pythonでも ++i や --i と書くことはできる。書くことはできるが、Pythonでは ++ や -- はインクリメント/デクリメント演算子ではなく、単項の + や - を二つ続けて書いているだけで、こう書いたのと同じ結果になるだけだ。
++i == +(+(i)) --i == -(-(i))
だが、ここで重要なのは、この式はコンパイルエラーにはならないという事実だ。コンパイルエラーにならないということは、すなわち抽象構文木(AST)を作れるということだ。そしてASTを作れるということは、みんな大好きastモジュールで好き勝手できるということなのである。
import ast class InclTransformer(ast.NodeTransformer): def visit_Expr(self, node): if isinstance(node.value, ast.UnaryOp): if isinstance(node.value.op, ast.UAdd): if isinstance(node.value.operand, ast.UnaryOp): if isinstance(node.value.operand.op, ast.UAdd): num = ast.copy_location(ast.Num(n=1), node) n = ast.AugAssign( target=node.value.operand.operand, op=ast.Add(), value=num) return ast.copy_location(n, node) return node s = """ def inc(i): ++i return i """ m = ast.parse(s, "filename", "exec") exec compile(InclTransformer().visit(m), "filename", "exec") in globals() print inc(99)
2012-10-02
Python3.3のdecimalが馬鹿っぱやい件
Python 3.3 では decimalモジュールがC言語で実装され、10進浮動少数演算が馬鹿っぱやになりました。
単純なニュートン法で平方根を計算してみると、
def newton(n): guess = n/2 better = (guess + n/guess)/2 while better != guess: guess = better better = (guess + n/guess)/2 return guess
Python2.7では
浮動少数点
$ python -m timeit "import decimal;import newton;newton.newton(2.0)" 100000 loops, best of 3: 2.73 usec per loop
decimal
$ python -m timeit "import decimal;import newton;newton.newton(decimal.Decimal('2.0'))"
1000 loops, best of 3: 649 usec per loop
Python 3.3では
浮動少数点
$ python3 -m timeit "import decimal;import newton;newton.newton(2.0)" 100000 loops, best of 3: 3.56 usec per loop
decimal
$ python3 -m timeit "import decimal;import newton;newton.newton(decimal.Decimal('2.0'))"
100000 loops, best of 3: 13.6 usec per loop
速くなったとは言ってもfloatの数倍はかかってしまうレベルではあるが、それでももともとPythonの浮動小数点演算なんて別に速いというほどのものではない。どっちにしろ遅いんだから、この程度の差なら数値演算が主なスクリプト以外では、全てDecimalで済ませてしまっても問題ないというレベルではないだろうか。
2012-09-21
Pandocでblockdiagを使う
最近、ドキュメント生成ツールとして Pandoc をちょっと試している。Markdownで手軽に書けて、reStructuredTextよりも好みだ。
Pandocというのは「ドキュメント生成ツール」ではなく、正確に言えば「ドキュメント変換ツール」だ。MarkdownからHTMLやPDFへの変換だけでなく、MarkdownからreStructuredTextへの変換や、HTMLからテキストファイルへの変換などもできるようになっている。
そしてその変換のフォーマットとして、Pandocの抽象構文木をそのままJSON形式などでの入出力がサポートされており、この機能を使えばpandoc本体に手を加えずともいろいろな機能を追加できるようになる。ということで、blockdiag を Markdownテキストに記述し、図を生成するフィルターを作成してみた。
このようなMarkdownから、
Example
------------
Following image was generated by blockdiag.
````blockdiag
{
世界の -> こ;
世界の -> み;
世界の -> か;
}
````
こんな画像が表示される
ソースはこちら - https://github.com/atsuoishimoto/pandoc-blockdiag-sample
本来はHaskellで書けば、Pandocモジュールを直接使ってもう少しシンプルにかけるが、ここではあえてPythonで書いている。決してHaskellから逃げたのではない、という点をご理解いただければ幸いである。
