Pythonでdisってみた

以前dict()とリテラルで{}と書いた時の違いにコンストラクタ的なものが呼び出されないという記憶があったような無かったような気がしたけど、いい調べ方が思いつかなかったので放置してました。
が、今日[twitter:@methane]さんがエキスパートPythonプログラミングのリスト内包表記の解説補足をしていた記事をみてdisモジュール使ってdisればいいんじゃね?という事でdisって見ました。

disったコード

まず、空のディクショナリ生成のコード。
dict()

def dict_init():
    hoge = dict()

リテラル

def dict_literal():
    hoge = {}

で、disるコード。

dis.dis(dict1.dict_init)
dis.dis(dict2.dict_literal)

実行結果。

  4           0 LOAD_GLOBAL              0 (dict)
              3 CALL_FUNCTION            0
              6 STORE_FAST               0 (hoge)
              9 LOAD_CONST               0 (None)
             12 RETURN_VALUE        
  4           0 BUILD_MAP                0
              3 STORE_FAST               0 (hoge)
              6 LOAD_CONST               0 (None)
              9 RETURN_VALUE        

これの見方は左の列から、ソースの行番号、バイト数、ニモニック、参照変数インデックスとなるらしい。
で、結果を見るとやぱりdict()の方は何かの関数を呼んでいるみたいですね。
バイト数を単純に比較するだけならリテラルで書いた方が早いとうことも分かりました。

次に辞書に{'a': 'a'}が入るようなデータをリテラルとdict()バージョンの2つで見てみると結果は、

  4           0 LOAD_GLOBAL              0 (dict)
              3 LOAD_CONST               1 ('a')
              6 LOAD_CONST               1 ('a')
              9 CALL_FUNCTION          256
             12 STORE_FAST               0 (hoge)
             15 LOAD_CONST               0 (None)
             18 RETURN_VALUE        
  4           0 BUILD_MAP                1
              3 LOAD_CONST               1 ('a')
              6 LOAD_CONST               1 ('a')
              9 STORE_MAP           
             10 STORE_FAST               0 (hoge)
             13 LOAD_CONST               0 (None)
             16 RETURN_VALUE        

となった。
やっぱりリテラルで書いた方が早いですね。

ちなみに最後のRETURN_VALUEはNoneを返しているらしい。
return文を端折った場合は暗黙的にNoneを返すというのをどこかで見たんだけど詳しく覚えてない・・・

話を元に戻してdict()の中のCALL_FUNCTIONは何を呼んでいるのかというのはどの先はソースみるしかないなーということでそのうちまた書きます。

fizzbuzz関数のif文無し・ワンライナー縛り

Flexで仕事していてたまに長いビルドがかかる時とかにちょろっと自動化のスクリプト書いたりしてるんですが、その時タイプミスしたことに気づかず実行したときに論理演算子のトリッキーな使い方を見つけた。

それが以下のコード。ちなみに言語はPythonです。

>>> hoge or "piyo": #hoge == False
'piyo'

おわかり頂けただろうか。
少しコードを変えて見てみよう。

>>> hoge and "piyo": #hoge == True
piyo

正直なんでこうなるかっつーのはよく理解してないんだけどまあこんな仕様なんだろうということで遊び半分でfizzbuzz関数を書いてみた。

#! python
# -*- coding:utf-8 -*-

import unittest

def fizzbuzz(num):
    return num % 15 == 0 and "fizzbuzz" or num % 3 == 0 and "fizz" or num % 5 == 0 and "buzz" or str(num)


class TestFizzbuzz(unittest.TestCase):

    def test_return_fizz(self):
        self.assertEquals("fizz", fizzbuzz(3));
        self.assertEquals("fizz", fizzbuzz(6));

    def test_return_buzz(self):
        self.assertEquals("buzz", fizzbuzz(5));
        self.assertEquals("buzz", fizzbuzz(10));

    def test_return_fizzbuzz(self):
        self.assertEquals("fizzbuzz", fizzbuzz(15));
        self.assertEquals("fizzbuzz", fizzbuzz(30));

    def test_return_num(self):
        self.assertEquals("1", fizzbuzz(1));
        self.assertEquals("2", fizzbuzz(2));


if __name__ == "__main__":
    unittest.main()

上の実行結果がこれ。

....
----------------------------------------------------------------------
Ran 4 tests in 0.000s

OK

見ての通りオールグリーンですよ!
fizzbuzzの定義はキモいですね!!
というかよくわかりませんね!!!

別の言語では?

とりあえずやってみたのはRubyJavaScriptJava
xUnitはめんどいので端折りましたが、目視レベルで確認済み。
Javaは関数定義の時点で&&演算子はboolean型とString型で比較できませんよとコンパイラに怒られてアウトでした。

Ruby

def fizzbuzz(num)
	return num % 15 == 0 && 'fizzbuzz' || num % 3 == 0 && 'fizz' || num % 5 == 0 && 'buzz' || num.to_s()
end

JavaScript

function fizzbuzz(num){
	return num % 5 == 0 && num % 3 == 0 && "fizzbuzz" || num % 3 == 0 && "fizz" || num % 5 == 0 && "buzz" || num.toString();
}

Java

public static String fizzbuzz(int num) {
    return num % 3 == 0 && "fizz";
}

以上の事からダックタイピングできる言語はできて、演算子オーバーライドができる言語ではキモいfizzbuzzができそうですね。

Progression勉強会第1回に参加してきた

WCAF分科会のProgresson勉強会に参加してきました。
いつも会場提供してくださるサーフボードさん、主催していただいた@shirokuro331さんありがとうございました。

参加理由

ぶっちゃけ「Progression?何それおいしいの?」状態で参加したんですが、@shirokuro331の絶妙なセッション構成(後述)で分かりやすかった!
で、本当の目的はFlexで使えるのか?という疑問を解消するために行きました。ハイ。
CairngormとかPureMVC使えよってツッコミはやめてw

セッション

セッションは

  1. Progression って何? by @shirokuro331
  2. コンポーネンスタイルでの制作チュートリアル by @mathuatlle
  3. クラススタイルでの制作チュートリアル by @itsuki_kousen
  4. FileMakerXML管理 by @samba
  5. Progression in Flex by @coelacanth

という流れで進んだので、正直最初はキャスト?シーン?と分からない事だらけでした。
発表の最中ぐぐってだいたいの概要だけはつかんでおいたものの噛み砕けない部分がいくつかあった。
でもクラススタイルでの制作チュートリアルではASのお話が入り、ここでは自分の領域にだいぶ近づきつつFlashでの開発チュートリアルを進めたので8割方理解できたと思う。
んで最後にFlexと完全に自分の領域に入って実際に開発してみたというLTだったので個人的に段階追って理解できました。

結論

結論としてはOOPのガチFlashアプリ作るならやっぱりCairngormとかPureMVC使えよってなった訳だが。
Progressionはハック対象として遊ぼうかなーという感じ。
いろいろ遊んだ結果は次回以降に発表しようかな。
あくまでも次回以降ですよw

Progression勉強会第1回に参加してきた

WCAF分科会のProgresson勉強会に参加してきました。
いつも会場提供してくださるサーフボードさん、主催していただいた@shirokuro331さんありがとうございました。

参加理由

ぶっちゃけ「Progression?何それおいしいの?」状態で参加したんですが、@shirokuro331の絶妙なセッション構成(後述)で分かりやすかった!
で、本当の目的はFlexで使えるのか?という疑問を解消するために行きました。ハイ。
CairngormとかPureMVC使えよってツッコミはやめてw

セッション

セッションは

  1. Progression って何? by @shirokuro331
  2. コンポーネンスタイルでの制作チュートリアル by @mathuatlle
  3. クラススタイルでの制作チュートリアル by @itsuki_kousen
  4. FileMakerXML管理 by @samba
  5. Progression in Flex by @coelacanth

という流れで進んだので、正直最初はキャスト?シーン?と分からない事だらけでした。
発表の最中ぐぐってだいたいの概要だけはつかんでおいたものの噛み砕けない部分がいくつかあった。
でもクラススタイルでの制作チュートリアルではASのお話が入り、ここでは自分の領域にだいぶ近づきつつFlashでの開発チュートリアルを進めたので8割方理解できたと思う。
んで最後にFlexと完全に自分の領域に入って実際に開発してみたというLTだったので個人的に段階追って理解できました。

結論

結論としてはOOPのガチFlashアプリ作るならやっぱりCairngormとかPureMVC使えよってなった訳だが。
Progressionはハック対象として遊ぼうかなーという感じ。
いろいろ遊んだ結果は次回以降に発表しようかな。
あくまでも次回以降ですよw

unittest2パッケージと2.7のunittestモジュールまとめ

以前ブログに書いたparameterized testがPython2.7で実装されるという事が気になり始めたので、おもむろにPython2.7b2のWhat's Newの章を読んでみた。
すると、unittest2というパッケージが外部ライブラリとしてあるようだ。
urllib2的なノリかと思ってみたら、2.7で実装される機能のバックポートらしい。
一足先に使いたい人はeasy_installでインスコしてね!

簡単なまとめ

2.7b2の公式ドキュメントから簡単にまとめてみた。
unittest2も多分同じ感じで使えると思う。
詳細はunittest2の使い方を見てくださいませ。
http://www.voidspace.org.uk/python/articles/unittest2.shtml

また、訳が間違ってるなどあったら指摘お願いいたしまする。

  • py.testやnoseほど強力では無いがtestモジュールを検出して実行できるようになった
    • unittest.TestLoader.discoverメソッドを使う
    • ライブラリリファレンス見る限りワイルドカードを使ってるような
  • main()関数のオプション追加
    • バッファオプション
      • 標準出力に出力しないでバッファリングする。出力のタイミングはすべてのテスト完了かテスト失敗時
    • Ctrl + Cの割り込み
      • 割り込みがあった時点で完了したテストを出力して終了
        • たしか今まではKeyboardInterruptの例外が出て、これがハンドルされず落ちるというような感じだったと思う
    • failfastオプション
      • テストが失敗した時点でテスト終了
  • 対話モードでのテストの進捗の出力
    • xが失敗時、uが想定外の成功(なんか訳怪しい
  • テストのスキップ
    • ある条件でのテストをスキップするとか
      • 使いどころとしてはフィクスチャでテストデータ投入に失敗したらパスとかっぽい
  • テスト失敗時の詳細なメッセージの出力
    • assertEqual, assertFalse, assertTrueが対象
  • assertRaisesメソッドにwith文が使えるようになった
    • with self.assertRaises(expression)の後の行に例外が発生する処理を書く
  • クラスおよびモジュールレベルでのフィクスチャ追加
    • setUpModuleとかtearDownClassとか
  • cleanupメソッドの追加
    • setUpが失敗した場合に実行する関数
  • assert関数の大幅な追加・変更
    • 大杉。公式ドキュメント見て。
  • unittest.main()関数にexit引数の追加
    • main関数がFalseを返すときにはsys.exit()を実行しない
  • TestResultクラスにstartpTestRun()メソッド、stopTestRun()メソッドの追加
    • startTestRunはテスト開始後に一度だけ呼び出す。stopTestRunは終了後に一度だけ呼び出す。


ちなみに2.7はまだベータなので変更・追加される可能性はある。
その時はまた新たに差分のみを新規に起こすかここに追記します。

parametarized testは?

まだ問題があるみたいでパッケージには入ってない。
残念。

余談

unittestのファイルは分割されたらしい。
でも今まで通りimportして使えるから安心してね!
って書いてあった。
コード読んでみるか。

余談その2

unittest2の作者はIronPython in Actionの作者だそうです。

noseドキュメント翻訳の問題点

nose-devのオーナーに出したメールが返ってきた。

こちらが投げたメールは

  • 今から翻訳やるよ!
  • 既に翻訳されているか知ってたら教えてください

という内容。
返信の内容は三行で書くと、

  • 大部分のドキュメントはdocstringに書かれてるよ!
  • 翻訳しようと思ったらHTMLを翻訳するのが簡単だけどメンテ難しいよね。
  • でもソースの方は弄らないでね!

という内容。
最後になんかいい方法あったら教えてあげる見たいなことが書いてあったのでちょっと期待しておこう。

とりあえず思いついた方法

個人的にはdocstringだけ抜き出すスクリプト書いてそこから訳するのが無難かなあと。
でもそれやるとdoc関数で見た時に英語になるんだよなあ。
でもソースの方弄るなって言われてるし・・・

しかし当面の間は*.rstの翻訳をしてると思うし、いろいろ体裁を整えたり等の作業があるのでこの件をやんわり調査しつつ問題の先送りをします。
その頃にはnose-devのオーナーから何か助言があるかもしれないし・・・

noseドキュメント翻訳はじめました

Pythonのテスティングフレームワークであるnoseの翻訳を始めてみた。
第1の目的はnoseを知るより、SphinxとreSTの習得だったりする。
んでその次がnoseの習得という。

問題はどこに公開するかだなあ。
まあHTMLの公開先については追々決めていこうかと。
今はMercurialで管理しているので、BitBucketかどっかに晒す予定。