使っ - みる会図書館


検索対象: Pythonクックブック
521件見つかりました。

1. Pythonクックブック

152 ー 4 章ショートカット ネギなどで煮込んだイタリア料理 ) といったものがあるはすだということだった。これらは普通、デザート、 前菜、肉料理という割と典型的なカテゴリーに、あるいはあまり美味そうでない非比喩的対応物、すなわち ファイル、アルゴリズムなどのカテゴリーに入るであろう。我々はカテゴリーをリストアップし、これをレ シピの収集に使えるよう z 叩 e サイトに反映し、それから水門を開いたのである。 すぐに明らかになった。投稿には前もって決めたカテゴリーにあわないものがあるのだ。これには理由が あり、それも料理から説明がっくものだった。つまりこの章に入ったレシピは、ルー ( 古典的フランス料理の 素養のない人のために書いておくと、汕と粉を炒めたもので、ソースを作るのに使う ) を作り、生地をこね、 粉をふるい、黄身と白身を分け、鍋を振り、湯むきをし、などなど、ちゃんとしたコックなら知ってるに決 まっているが料理本には書いていない無数の技の thon 版であった。こうした技やテクニックは料理に使う ものではあるが、個々の分野に分類することは難しい。だから手の込んだレシピを探し当てた初心者コック であるあなたは、すぐにイライラすることになる。ちゃんとした調理書の筆者はこの手のテクニックを自明 と考えるので、彼らがこういうものを説明する ( イラスト入りでね ! ) のはたとえば「離婚した中年男の料理』 などというタイトルの本でのみなのだ。この貴重なる分野を本から追い出したくなかったので、新しいカテ ゴリーが誕生した ( スマン、イラストはなしだ ) 。 初版の「イントロダクション」では先見的にもこう言ったものだ・ この章のレシピは本の中でも最もうつろいやすいものであろう。なぜなら人々がショートカットある いは注目に値するテクニックと考えるものは、最新の言語機能を割とそのまま使ったイディオム的な ものになりやすいからだ。 堂々と言おう。私は正しかった。最新の言語定義に特にフォーカスを当てたこの新版により、以前のレシピ の多くには意義がなくなった。初版出版から 2 度のリリースを経て、すなわち thon2.3 と 2.4 により、 れらのレシピのアイディアは、多くが構文機能やライプラリ関数として取り込まれた 衄はよりクリーン 0 に 1 ロロ でコンパクト、かつまだまだパワフル、使う楽しさは今も 10 年以上前に匹敵する、というものになった。そ れは、これまでのメジャーリリースすべてと同様のことである。 こうしてこの章のレシピの半分がまったく新しいものとなったにれはこの本の残り全部とほば同じ割合で ある ) 。残りの半分は初版にあったレシピの大幅な改訂版である ( 多くは単純化した ) 。単純化と、初版でサポー トしていた全バージョン向けに解説を完備するのをやめた ( フォーカスするバージョンを 2.3 と 2.4 に絞った ) ことにより、この章および本書全体には初版より 1 / 3 ほど多くのレシピが入っている。 大幅な改訂を受けたこの章にも言語のもっとも根本的で変化のない側面、すなわち代入、結合、コピー、参 照さらにはシーケンス、ディクショナリなどのセマンティクスに触れた多くのレシピがあるが、これについ て突っ込んだことを言ってもしようがないだろう。これらの概念はどれもプログラミングに対する thon 的 アプローチの鍵であり、 こうしたレシピが何年も生き残っているのを見ると、 thon が今後数年でこの方面 への進化を遂げるかどうか疑問に思わざるを得ない。

2. Pythonクックブック

4.1 オブジェクトのコピーー 155 のにも役立つ ) 設けることは可能だ。自分クラスのインスタンスのディープコピー方法をカスタマイズしたい 場合、特殊メソッドー deep ( opy ーを与えればよい ( 「レシピ 6.9 オプジェクトのコピーを素早く」を参照 ) 。 文字列、数値、タブルと言った不変オプジェクトをコピーする必要はないことには注意されたい。改変の 心配がないからである。ちなみにコピーしてもオリジナルが戻ってくるだけで何も危険なことはないが、時 間とコードの無駄だ・ 'cat' = copy. copy(s) > > 〉 S iS t True is 演算子は、 2 つのオプジェクトが完全な等値性を持たないが事実上は等しい、ということをチェックする ()s は同一性のチェックである。完全な等値性のチェックには = = 演算子を使うこと ) 。不変オプジェクトに同 一性チェックをかけても特に有用なことはなにもない ( ここでそれを使っているのは copy. ( opy が無害だが使 い物になっていないことを示すためだ ) 。だが可変オプジェクトではこれが極めて重要になる場合がある。た とえば名前 a と b が同じオプジェクトを指しているのか異なったものを指しているのか確信が持てない場合に 簡潔で非常に高速なチェック a is b をかければ、どうなっているか教えてくれる。改変をかける前にコピー を作る必要があるかどうかは、これで判るのだ ( オリジナル状態のオプジェクトを無変更で取っておきたい場 合である ) 。 コピーを生成する方法は他にも 2 級の、文字通り自分で構築するというやり方がいろいろある。リ スト L に対し、「全オブジェクトスライス」の L [ : ] やリスト内包 [ x for x in L ] をかければ、た しかに L の ( シャロー ) コピーができる。空リストを加算する L + [ ] 、リストに ] で乗算を行う L * 1ist(L) をコール 1 なども同様だ。しかしこれらはすべて無駄であり、混乱の元にしかならない した方がすっとクリアで高速だ。とはいえ、 L [ : ] の構文には慣れておくべきだ。なぜなら歴史的理 由により広く使われているからである。つまり、これは使ってはいけないよ、と完璧に教え込まれ た人でも、他の人の Python コードを見れば目にすることになるのである。 同様に dictiona 「 Y d に関しても、ループによりシャローコピー dl を生成することができる : 〉〉 > dl ニ > 〉 > fO て somekey in d : dl[somekey] = d[somekey] もしくはもっと簡潔に、 dl = { } ; dl. update ( d ) というのもある。しかし、繰り返しになるが、こ んなコーディンクは時間と労力の無駄で、混乱以外なにひとつ生み出さないデブなのろまにすきな ライプラリリファレンスおよび fPython クイックリファレンス」の copy モジュール部。 参照 い。 dl = di ( t ( d ) とやって、ハッピーに行こう。

3. Pythonクックブック

192 ー 4 章ショートカット 考察 複数のバージョンの th 。 n ( またはサードバーテイバッケージ ) をサポートするコードを書く場合、あなた のモジュールの多くは以下のようなコード片で始めざるを得ない ( 以下は名前 set がビルトインになっている thon2.4 でも、標準ライプラリから取得せねばならぬ 2.3 でも正しくセットされていることを保証するコー try: s et except NameError: from sets import Set as set レシピはこの種のロジックを簡約する。コードがデフォルトで builtin モジュールに働くのは、古い thon にない名前があるときに、処理すべき典型的なモジュールがこれだからだ。このレシピを使うと、名 前 set がビルトインとして正しく定義されていることが、プログラム初期化の際にたった一度、次の 1 行を コールするだけで保証される : ' from sets import Set as set ・ ) ensureDefined(lset' このレシピの利点は、たくさんのモジュールの頭にアドホックなれ y / ex ( ept 文をばらまく代わりに、アプ リケーション中で必要な ensureDefined のコールをすべて 1 つに、つまり初期化の部分にまとめられることで ある。加えてこれは読みやすい。 ensureDefined は 1 つの特定の仕事のみをするので、これをコールする目的 は明らかだが、 t て y / except 文はいろいろな目的があり得るので、理解するのによく読んで考えなければならな い場合がある。さらにもう 1 つ。このレシピを使うと、 pychecker (http://pychecker.sourceforge.net/) のよう な有用なチェックツールの使用時に、 try / except アプローチが引き起こすかもしれない警告を回避する ( もし pychecker やこれに似たものを使ってないなら、使うべきですよ ! ) 。 レシピでは補助ディクショナリ d を exec 文のターゲットとし、それから指定の名前のみを移転することで、 target への意図せぬ事故的副作用を回避するよう注意を払った。こうすることで、たとえば target としてモ ジュールでないオプジェクト ( たとえばクラスだが、インスタンスの場合もある ) を使う場合、これに builtins という名の属性 ( thon のビルトインのディクショナリへの参照 ) を追加せずにすむ。これがも し、 if 文の本体を : exec defining code in vars(target) としてしまっていると、 http://www.python.org/doc/current/ref/exec.html に記されているこの副作用を、ま ともに受けることになる。 exe ( は thon コードとして有効な文字列を与えれば何でも実行できるし、してしまう。これを意識してお くのは重要である。すなわち、 ensureDefined 関数のコールに渡す引数 defining ー ( ode が信用できないソース、 つまり悪意を以ていじられたかもしれないテキストファイルなどに由来しないのを、必ず確認すること。 参照 オンラインのリファレンスマニュアルの exec の解説 (http://www.python.jp/doc/release/ref/exec.html) 。

4. Pythonクックブック

9. O イントロダクション一 361 る。特に GIL はまったく同じように働く。 GIL の決定的利点とは、 c で thon 拡張を書くのが実に簡単にな ることにある。 C コードの呼び出しから thon コードに戻るまで、拡張が GIL を明示的に解放しない限り、 スレッドのスイッチは起こらないのである。この利点が非常に重要になるのは、 c ライプラリの一部がスレッ ドセーフでない thon 環境で、自作の拡張が使えるようにしたい場合だ。自作の c コードがスレッドセーフ である場合、計算や I / O 操作が続く周辺で、それなりの時間 thonCAP1 コールを必要としないなら、 GIL の解放が可能であり、またそうすべきである。こうするとその c 拡張を使った thon プログラムはプロセス 内で複数のスレッドを使うため、複数プロセッサによるアドバンテージを得ることが可能となる。ただし、 Python C API のエントリポイントをコールする前に GIL を再取得するのを忘れてはならない。 スレッド間で共有されたデータ構造体にアクセスしたい場合、その操作がアトミックかどうか、つまりス レッドのスイッチがその操作中に起きないか ( または起きるか ) が問題になることがある。基本的には複数の バイトコードから成るものは全てアトミックでない。あるバイトコードから次のバイトコードへ、スレッド のスイッチは常に起こりうるのである ( 標準ライプラリ関数 dis. dis を使うと python コードをバイトコード ーモニックに逆アセンプル可能である ) 。さらに言えば単一のバイトコードすらアトミックでない場合が存 在する。バイトコードが任意の Python コードをコールバックできる場合である ( バイトコードは最終的に Python コードの特殊メソッドを実行するかもしれないから ) 。もっとも賢明なやり方は、疑わしいもの全てを アトミックでないと想定し、 2 つ以上のスレッドからアクセスされるデータ構造体をギリギリの最小限しか使 わす ( ただし Queue. Queue のインスタンスを除く。これはスレッドセーフであるよう特に設計されている ! ) 、 あとのデータ構造体をロックで確実にアクセス保護することだ。 ロックは次のイディオムで行うとまず間違いない・ somelock. acquire( ) try: # ロックを必要とする操作 ( 最小限に ! ) finally: somelock. release( ) try/finally 構造は、 try 節の中で例外が起きてもロックが解放されることを確実にする。予期せぬ例外で ロックの解放に失敗して、アプリケーション全体がきしみを上げつつ止まることを防ぐのだ。また、複数の ロックを連続して取得するのは慎重に。本当にどうしても必要ならば、異なるロックを連続的に取得する場 合の道筋をコード全体で完全に確認することである。でなければ遅かれ早かれ、必す惨状を引き起こすケー スに突入する。 2 つのスレッドが互いに互いの持っているロックを取得しようとする状態、デッドロックだ。 これはあなたのプログラムは死んだも同然という意味でもある。 th て eading モジュールで特に重要なのは、スレッドやさまざまな高次同期構造を表現する種々のクラス群で ある。 Thread クラスは個々の制御スレッドを表現する。これは呼び出し可能オプジェクトをコンストラクタに 渡すことにより、または run メソッドをオーバーライドすることにより、成すべきことを知らされる。スレッ ドは st 訂 t メソッドのコールで他のスレッドが起動できる。 join のコールで完了を待っこともできる。 python はまたデーモンスレッドをもサポートする。デーモンスレッドは同じプログラム中の非デーモンスレッドが 全て終了するまでバックグランドで処理をして、最後に自動的に終了する。 threading モジュールの同期構造にはロック、リエントラント ( 再入可能 ) ロック ( 単一のスレッドがデッド

5. Pythonクックブック

566 ー 14 章ウェブプログラミング らアイテムを 1 つ 1 つレンダリングする sequence 、もう 1 つはディクショナリなどのマッピング型を使う mapping である。後者では nevow : slot タグの name 属性として書かれた各キーをもとに、アイテムのレンダリングを行 う。もっと一般的な話をすると、て end. Page をサプクラス化した中では自前のレンダリング法がコードできる のである。 レシピは Pg クラスの定義の後、 site オプジェクトの構築、 application オプジェクトの構築、この site と application を使った 8080 番ポートの TCPse Ⅳ er の構築と続くが、これは Twisted の一般的なイディオムで ある。レシピのコードをセープしたソースファイル nsa. tac は python インタープリタから普通に実行するので はなく、 Twisted の一部である twistd コマンドとともに実行すべきものだ。 twistd は起動、デーモン化、ロギ ングまわりなど、実行時に渡されたフラグによりさまざまな処理を行う。 twistd と共に実行するソースファイ ルには拡張子 . tac を使い、通常 python が実行するコードの . py と区別を付ける習慣になっているのはこのた めだ。 レシピのコードは実験的で玩具的なので、 twistd の起動フラグとして - noy を付けるべきである。こうすれ ばプログラムはフォアグランドで実行され、通常はファイルに出力されるログが標準出力に出てくるように なるからだ。 Twisted のドキュメントの twistd の部分をすべて読み、フラグによるオプションをきちんと見て おくともっとよいだろう。 参照 Twisted は http://www.twistedmatrix.com に、 Nevow は http://nevow.com/ にある。 1 生 14 任意のオプジェクトを Nevow でウエプ化 Credit: VaIentino VoIonghi, Matt GoodaIl 訳 : 鴨澤眞夫 問題 ネットワーキングフレームワーク Twisted でウェブアプリケーションを書いており、 Nevow サ プシステムをウェブレンダリングに使っている。任意の python オブジェクトをウェブページに self. 1astName = 1astName self. firstName = firstName def init (self, firstName, IastName, nickname) : class Person(0bject) : # 「アプリケーションテータ」の例としてシンプルなクラスをいくつか 行 om nevow import tags as T from nevow import appserver, rend from twisted. application import internet, service はその動作を示した、おもちゃのようなウエプサーバースクリプトの例である : この場合、 Twisted と Nevow の組み合わせではインタフェースとアダブタによるアプローチを取る。以下 解法 レンダリングする必要がある。

6. Pythonクックブック

228 ー 5 章サーチとソート 考察 ディクショナリはキー ( 競技における参加者の名前など ) と「スコア」 ( 競技者のそれまでの得点、オークショ ンで競り人の出した最高値など ) の対応を格納するデータ構造として、さまざまな意味で自然だ。ディクショ ナリを使う場合、自然川頁ーースコアが昇順にならぶ順序ーーでアクセスしたいと思う場合が多いだろうし、現 在の「スコア」 ( 3 位に付けてる競技者の名前、 2 位のスコアなど ) に応じたランキング ( rating ) にも高速にア クセスしたいはずだ。 レシピではこれを達成するために di ( t のサプクラスを作り、 dict では完全に欠落している必須機能は ating 、 getVa1ueByRating 、 getKeyByRating の各メソッド ) を追加している。さらに微妙かつ重要なのは、 keys および関 連の各メソッドを改変し、それらが要求の順序 ( スコアが昇順になる順序、つまり 2 つのキーのスコアが同一 であったときは引き分けの解消が必要で、このときはキー同士を暗黙に直接比較する ) で整列したリストや反 復子を返すようにしたことである。詳細解説のほとんどはクラス自体の do ( st ⅱ ng にあるが、これも実は大き なポイントである。つまりドキュメントと用例をここで保守しておけば doctest モジュールが使えるのである。 doctest はユニットテスト機能をもたらし用例の検証を行ってくれる thon 標準ライプラリモジュールである。 この実装で一番おもしろいのは、パフォーマンスに深刻な影響を与えずポイラープレート ( 繰り返される退 屈なコードで、つまりもっともバグが隠れていそうな場所 ) を最小限に処理しているあたりだ。クラス Ratings はクラス di ( t とクラス Di ( tMixin から多重継承を行っているが、このとき基底クラスリストで後者を先に置い ている。このため本体で明示的にオーバーライドしていないメソッドはすべて DictMixin から来ることになる。 Raymond Hettinger の DictMixin クラスは、もともとオンライン版の・・巧 , thon Cookbook" にレシピとして 投稿され、のちに thon2.3 で標準ライプラリに入ったものだ。 Di ( tMixin にはマッピング関連のメソッドが すべて入っているが、 init_ および ( opy メソッド、それに _getitem setitem delitem 、そし て最後に ( 重要さでは最後でない ) keys という 4 つの基礎的メソッドが入っていない。自分で書いたマッピン グクラスで、完全なマッピングクラスが持つ数多くのメソッドをすべてサポートしたいなら、基礎的メソッ ドのみを補完 ( セマンティクスに応じて。たとえば不変インスタンスを持つクラスなら変更メソッドの setitem と delitem は補完不要 ) した DictMixin のサプクラスを作るべきだろう。 DictMixin に実装済み のメソッドを、パフォーマンス狙いでオーバーライドするのもよい。 DictMixin のアーキティクチャは、全体 として古典的な TemplateMethod デザインパターンの好例、その mix - in による有用な変種と見ることが できる。 レシピのクラスは、 getitem ーをもうひとつの基底クラス ( つまりビルトイン di ( t ) から継承し、またパ フォーマンスのために、可能な限りのものを di ( t に明示的に委譲した。基本的な変更メソッド ( setitem と delitem ) をわざわざコーディングする必要があったのは、 ( 基底クラス di ( t への委譲に加え ) 補助デー タ構造の self. rating を保守しなければならないためだ。 self. rating は (score, key ) ペアによるリストで、 標準ライプラリモジュール bise ( t の助けを借りてソート状態を保っている。 keys も自分で実装し ( またこのと き iter も実装したーーー実のところ iterkey もである。 keys は明らかに iter を使って実装するのが一 番簡単だった ) 、 self. ー rating を使って要求通りの順序でキーを返すようにしている。最後に実装が自明であ る init_ と copy 、それに我々の供給する 3 つのレーティング関係のメソッドを加えた。 こうして、バランスが取れて簡潔、平明、かっ標準 thon ライプラリから非常に多くの機能を慎重に再利 用したおもしろい例ができ上がった。アプリケーションに使ってプロファイリングしてみると、 DictMixin か ら継承したメソッドのパフォーマンスにあまり満足できないことに気付くかもしれない。つまるところ、

7. Pythonクックブック

414 ー 10äシステム管理 示することができる。 標準ライプラリの email モジュールには、メール本文のパースや、ディクショナリ的なインデックス構文に よるメールヘッダーへのアクセスなど、必要な機能がすべて含まれている。最近見たメール用にある程度の 「記憶」も必要だ。幸い、全てのメールの重複が、数分の間に発生していることに気付いたため、これらにつ 2 時間分で有り余るほどだ。というわけで、メールの受信時 いて、長い時間憶えておく必要はなかった 刻と ID の記憶はテキストファイルで行うことにした。こうした FIFO(First-In,First-Out) によるデータ保持に 参照 またも正解か ! ることが分かった。・・ Do the simplestthing that could possiblywork" ( 動作しそうで一番簡単なことをしろ ) が PC を使ってさえも、 ーズ ( 1 時間あたり数百通程度のメール処理 ) を満たすにはこのアプローチで十分であ ない新規メールが到着するたびに、テキストファイル全体を上書きするのだ。やってみると、私の少々古い はもっと良い方法を検討した方がよいとも思ったが、ますは簡単なアプローチを試してみた 重複してい ライプラリリファレンスおよび fpython クイックリファレンス』にある、 email パッケージと time 、 sys 、 の各モジュールに関する解説。 1 11 Windows のサウンドシステムをチェック Credit: Anand PiIIai 訳 : 木本守・鴨澤眞夫 問題 解法 thon 標準ライプラリにある winsound モジュールを使えば、簡単に調べられる : Windows のサウンド機能が適切に設定されているかどうかを調べたい。 import winsound try : winsound. P1aySound("*", winsound. SND ALIAS) except RuntimeError, e: print 'Sound system has problems, ' else: print 'Sound system is OK' 考察 サウンドシステムがこのレシピのテストをパスし、なお正しく音が出ないということはありうる OS にはスピーカの電源が切れていたというような単純なこと ( プログラムでこれを感知することはできない ! ) から、非常に微妙で複雑なことまで、ありとあらゆる原因がありうる。プログラム上サウンドが問題になる 場合、このレシピを使えば少なくとも、難解なデバイスドライバの設定を丹念に調べるべきか、まずはスピー カーの電源がついているかを調べるべきかが分かる。

8. Pythonクックブック

104 ー 2 章ファイル 解法 PyWin32 拡張モジュールを使えば、 COM (Component Object Model) を介して word 自体にアクセスし、 換を行なわせることができる : import fnmatch, OS, sys, win32com. client wordapp = win32com. client. gencache. EnsureDispatch("Word. App1ication") try : for path, dirs, files in os. walk(sys. argv[l]) : for filename in files : if not fnmatch. fnmatch(filename, = os. path. abspath(os. path. join(path, filename)) doc print processing %s" % doc wordapp. Documents. 0pen(doc) docastxt = doc[ : - 3 ] + 'txt' wordapp. ActiveDocument. SaveAs(docastxt, FiIeFormat=win32com. client. constants. wdFormatText) wordapp. ActiveDocument. ( lose ( ) finally: # 例外が発生した時でも Word が適切に終了されることを確実にする wordapp. Quit( ) 考察 変 ほとんどの Windows アプリケーションで助かるのは COM を通じてスクリプトが書けることであり、 pyWin 32 拡張モジュールは thon における COM スクリプトの作成を実に容易にしてくれる。この拡張モジュール で、 thon スクリプトにさまざまな種類の Windows の作業を実行させることが可能になる。このレシピでは Microso れ Word を操作して、あるディレクトリツリーに存在する全ての「 . doc 」ファイルから、それぞれ対 応する「 . ⅸ t 」テキストファイルへとテキストを抽出する。 os. walk 関数を使えば、再帰的な方法を使わすとも、 簡単な文でツリーの全てのサプディレクトリにアクセスできる。 fnmatch. fnmatch 関数によって、ファイル名 が妥当なワイルドカード、こでは「 . do ( 」にマッチするかどうかを確認できる。 word 文書のファイル名が 分かれば、 os. path の持つ関数でその名前を完全な絶対パスに変換し、 word で開いてテキスト形式で保存、そ の文書を再び閉じる。 もし Word を持っていなければ、全く異なるアプローチをする必要があるだろう。可能性としては、 word 文書を読み込むことのできる OpenOffice. 0鵬を使う方法がある。もう 1 つは、例えば http://www.winfield. demon. nl/ で入手できる Antiword ように、 Word 文書を読み込むために特別に設計されたプログラムを用い る方法である。しかしながら、これらの代替策については、まだ検証を行っていない。 参照 Python Programming on Win32" (Mark Hammond 、 Andy Robinson 著、 OReilly 発行 ) の PyWin3'2 に関 する部分、 http://msdn.microsoft.com の Microsoft word のオプジェクトモデルに関する Microsoft のドキュ メント、ライプラリリファレンスおよび fPython クイックリファレンス』の fnmatch 、 os. path 両モジュール

9. Pythonクックブック

354 ー 8 章デバッグとテスト import pretest if name maln # モジュールが import されたときのみ。メインスクリプトのときではない ! pretest. pretest( name ) 考察 一連のモジュールに変更を加えているとき、コードに改変があるたびに「自分をテスト」してくれる ( 自分 のユニットテストを自動実行してくれる ) と判っていれば安心だ ( 「改変があるたび」と「モジュールが再コン パイルされるたび」は同じだ。 thon はそのように見る。つまり、改変のあったモジュールを import すると き自動で再コンパイルを行うのだ ) 。テストの実行を自動化すると、ユニットテストの実行を忘れないように する、という重荷から解放される。テストはモジュールがメインスクリプトとして実行された時でなく、 import main ーっまり普通と された時に行われることに注意されたい。これはちょっと見慣れぬ if name は完全に逆のガードの下で実行されるのだ。 書き込みが常には許されないディレクトリに、自作モジュールの ( コンパイル済みの最新バイトコードファ イルを伴わない ) ソースを置かないよう注意すること。こいつはどんな事情があろうとバッドアイディアだ。 thon はコンパイルしたモジュールの . pyc ファイルをセープできす、毎回毎回再コンパイルを行なうため、 モジュールを import したアプリケーションの速度が低化するのである。この回避可能な再コンパイルによる 微妙な遅れに、毎度自動で実行されるユニットテストのパフォーマンス低下も加わるなんて、もう壮大なバッ ドアイディア ! としか言えないだろう。ちなみに自作モジュールを zip ファイルに入れておき、 こから直 接 import させる場合にもまったく同じ配慮がいる。要するに、「バイトコードが行けない場所にソースを置く な」である。さもなくばアプリケーションがモジュールを impo て t するたびに、不要な再コンパイルに ( そして 問題 Credit: John Nielsen 訳 : 鴨澤眞夫 8.10 doctest を unittest で使う ( Python2.4 ) の解説。 ライプラリリファレンスおよび IfPython クイックリファレンス』にある標準ライプラリモジュール unittest 参照 このレシピを使っていればユニットテストの再実行に ) さいなまれるだろう。 をユニットテストのためだけの「実行例」で散らかしたくないし、 unittest の強力さと几帳面さ doctest の簡単で直感的なアプローチによりユニットテストを書きたい。でもコードの docstring 解法 も捨て難い。 いつも以下のモジュール例 ( toy. py ) のように doctest を使っているとする :

10. Pythonクックブック

4.6 入れ子になったシーケンスの平滑化ー 163 のまま yield されるべきかが案外不明瞭だ、ということがある。私はこれを flatten に渡せるコーラブルな述 語引数に委譲し、自分では決めないことにした。コーラがタブルとリストのみ展開するという幾分簡単なデ フォルト動作で満足できる場合、これは何も指定しなくてよい。 flatten のモジュールの中には、他にも需要のありそうな述語を作っておくべきだろう。つまり、文字列 ( プ レーンおよび Unicode ) 以外の反復可能体をすべて展開するものだ。文字列は反復可能であるが、応用上はほ ば例外なくスカラーとして扱われ、サプシーケンスにはならないからである。 オプジェクトが反復可能であるかどうかは、そのオプジェクトに対してビルトイン iter をコールしてみれ ばわかる。オプジェクトが反復可能でないとき、このコールは TypeEr てを起こすのだ。オプジェクトが文字 列のように振る舞う ( string-like ) かどうかについては、オプジェクトが basestring のインスタンスであるか チェックすることで済ませた。オプジェクト 0bj について isinstance(obj, basestring) が True であれば、 のオプジェクトは basest ⅱ ng のサプクラスであり、すなわち string - ⅱ ke な型なのだ。というわけで、もう 1 つ の述語も簡単に書ける : def nonstring_iterable(obj) : try: iter(obj) except TypeError : return False else: return not isinstance(obj, basestring) これでコーラは文字列以外の反復可能型をすべて展開したいときに flatten(seq, nonstring_iterable) がコー ルできるようになった。ただしデフォルトを nonst ⅱ ng ー iterable にするのは確実にますい。上の方の例のよう に単純なケースで述語が nonst ⅱ ng ー ite て able になっていると、 list or tuple のときより最悪で約 3 倍遅くなる からだ。 flatten ジェネレータの非再帰版も書いてみた。こちらのバージョンは thon の再帰限度 ( 通常の環境では 数千以内 ) より深い入れ子のシーケンスをフラットにすることができる。再帰を除去するのに使った主なテク ニックは、明示的な後入れ先出し ( LIFO ) スタックの保持である。これは反復子から成るリストとして実装で きる。 def flatten(sequence, t0 expand=list or tuple) : = [ iter(sequence) ] iterators while iterators : # この時点で最も深い ( リストの最後の ) 反復子にループをかける for item in iterators [ -1 ] : if to expand(item) : # サプシーケンスがある。そちらの反復子をループしに行く iterators. append(iter(item)) break else: yield item # 最も深い反復子が終わった。親ループに戻る iterators. pop( ) else: