テキスト - みる会図書館


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

1. Pythonクックブック

1 章テキスト この memoizing の裏にあるのは、高コストなフォーマット準備を引数の組合わせごとに一度だけ行う ( それ から cache ディクショナリに格納する ) という考え方だ。もちろん他すべての最適化と同様、パフォーマンス 計測による評価で memoizing が本当にスピードアップにつながっているかチェックする必要はある。この場合、 memoizing を導入したことによるスピードアップは 30 ~ 40 % 程度であり、つまりこの関数がプログラムのパ フォーマンスポトルネックになっていない限り、やるだけの価値はないだろうということだ。 さて、「解法」のコード片でリスト内包を使ったものと等価の関数は以下のようになる : return split at(the line, xrange(), len(the line), n), lastfield) def split by(the line, n, 1astfie1d=Fa1se) : yield the line[last: ] if lastfield: last = cut yield the line[last:cut] fO て cut in cuts: last = 0 def split at(the line, cuts, lastfield=Fa1se) : まったく違ったアプローチとしては、ジェネレータを使うものがある : どちらの場合も struct. unpack よりリスト内包を使う方がわすかに好ましいことが判っている。 return pieces pieces. pop( ) if not lastfield : # 最後の断片が必要とされない場合は捨てる pleces = [ theline[i:j] for i, j in zip([0] + cuts, cuts + [None]) ] # 必要な大きさの断片に刻む def split at(theline, cuts, lastfield=False): 最後に挙げたコード片はこうなる : return pieces pieces. pop( ) if not lastfield and len(pieces[-l]) く n: # 最後の断片が短かく、かっ必要とされない場合は捨てる P1eces = [theline[k:k + n] f0 て k in xrange(), len(theline), n)] # 必要な大きさの断片に刻む def split by(theline, n, lastfield=Fa1se) : ジェネレータにピルトインの list をコールしてやればよい も ) 。フィールドのリストを実体化する必要があるのにジェネレータしか使えない、という場合には、その という場合に最適だ ( 明示的なループでも、 . j0in のように暗黙的な「アキュムレータ」をコールする場合で ジェネレータベースのアプローチは、その結果であるフィールドのシーケンスにはループが掛けたいだけ、

2. Pythonクックブック

406 ー IOäシステム管理 if x: "Can't run %s %s (%s)" % (editor, temp filename, x) raise RuntimeError, result = open(temp filename). read( ) os. unlink(temp filename) return result if name maln = edited text(' text go ahead, it's just a demonstration, after a11. 'Edit this text a little, print ' Edited text is: ' , text 考察 スクリプトでユーザから相当量のテキスト入力を受付けなければならないことがある。ユーザが好みのテ キストエデイタを使えるというのは、あれば素晴らしい機能であり、レシピではこの機能の方法を示した。私 は設定ファイルの調整やプログの書き込み、メールの送信に、このレシピの派生型を使用している。 もしこのスクリプトを Windows で使用する必要がないならば、 edit text 関数は、よりセキュアで少しシン プルなやり方で書ける : def edited text (starting text= temp file = tempfile. NamedTemporaryFile( ) temp file. write(starting text) temp file. seek(0) editor = what editor( ) = os. spawnlp(os. P WAIT, editor, editor, temp file. name) X "Can't run %s %s (%s)" % (editor, temp file. name, x) raise RuntimeError, return temp file. read( ) この手法はスクリプトから一時ファイルを開いたまま、テキストエデイタからもこの一時ファイルが編集 可能であることを前提にしているのだが、この機能は残念ながら Windows のほとんどのバージョンでサポー トされていない。レシピの edit text の方が移植性が高いのである。 設定ファイル等、文法その他の制限を守る必要があるファイルをこのレシピで編集する場合、ユーザが編 集時におかしたミスを分析して即時にフィードバックできるため、「入力 - 構文解析 - ェラー時再編集」のサ イクルにより、アプリケーションスクリプトはよりシンプルになり、作業はより効率的に行える。このよう なケースでは、理想的にはエラーのあった行にカーソルがある状態で再度ファイルを開くべきだろう。これ は Unix で動作するエデイタではだいたい可能で、たとえば 23 行目を開きたいとき、ファイル名に先立つ最 初の引数として " + 23 " を渡してやればよい。残念ながら、 Windows 上で動作するエデイタにはこのような引 数で混乱するものも多いので、 ( もし Windows をサポートする必要があるならば ) ここで難しい判断をしなく てはいけない。

3. Pythonクックブック

] 章テキスト class iStr(str) : case-insensitive な文字列クラス。 str と同じ振る舞いだが比較と検索では大文字小文字が無関係。 init_(self, *args) : self. lowered = str. lower(self) def _repr_(self) : return '%s(%s) ・ % (type(self). def hash_(self) : return hash(self. lowered) def lower(self) : return self. lowered def make case insensitive(name) : def name , str. repr (self)) ー st てのメソッドをラップして大文字小文字無関係な iStr のメソッドとする。 str meth = getattr(str, name) def x(self, other, *args) : ' other の小文字化を try する。 other は通常文字列だが、文字列は 非文字列と比較が可能であるため、ここで小文字化に問題が 出る場合もある。これに備えて 0ther を as-is で使うことも 視野に入れておく。 try: other = other. lower( ) except (TypeError, AttributeError, ValueError) : return str meth(self. lowered, other, *args) # Python 2.4 では x. func name=name を追加すること setattr(iStr, name, x) # 指定のメソッドに make case insensitive 関数を適用 for name in 'eq lt le gt gt ne cmp contains ・ . split( ) : make case insensitive(' ' % name) paSS f0 て name in 'count endswith find index rfind rindex startswith' . split( ) : make case insensitive(name) # ここでは replace, split, strip 等々のメソッドを変更してないが、 # お望みであれば追加は普通に可能 del make case insensitive # 以後不要なヘルノ←関数は削除すべし 考察 iStr クラスを実装する際のデザインチョイスについては、いくつか書いておく価値がある。まず init で 文字列の小文字バージョンを生成しておくようにしたことだ。 iStr の典型的な使い方で、これは何度も必要 になると予想されたためである。小文字バージョンはプライベートな属性に保持するが、あまりプライ べートすぎないようにした ( 名前がアンダースコア 2 つではなく 1 つで始まるようにした ) 。これは iStr が ( 「解 法」のコメントで示唆しているように、大文字小文字無関係の分割、置換などを供す拡張版を作るなどで ) サ プクラス化されたとき、サプクラスからこの重要な「実装詳細」にアクセスしたくなることが予想される

4. Pythonクックブック

496 ー 1 3 章ネットワークプログラミング # テータグラムは 1024 バイトまで受け取る data, addr = s. recvfrom(1024) data, "from", addr print "Received: これに対応する UDP クライアントスクリプト ( client. py ) は以下のように書く : import socket port = 8081 host = "localhost" = socket. socket(socket. AF INET, socket. SOCK DGRAM) S , (host, port)) s. sendto("HOIy Guid0! lt's working. 考察 ソケットデータグラムによる短いテキストメッセージ伝送は実装が簡単で、軽量なメッセージ伝達のイディ オムにもなっている。ただし信頼性保証が必要なデータ伝送にソケットデータグラムを使うべきではない。 サーバが対応できないときメッセージが失われるからだ。とはいえ、メッセージが消えても気にしなくてよ い状況や、伝送の失敗くらいでプログラムが止まると困る、くらいの場合は多い。 UDP データグラムのセンダ ( 上の例では「クライアント」 ) は sendto メソッドのコールまでソケットをバイ ンドしないことに注意してほしい。逆に UDP データグラムを受け取る場合、 recvfrom メソッドのコール以前 にソケットをバインドしていなければならない。 このレシピの簡単なコードを巨大なデータグラムメッセージの送信に、特にバッファリミットに無頓着な Wrndows 環境で使ってはならない。大きなメッセージを送る場合、次のようなものがお望みだろう : BUFSIZE = 1024 while msg : bytes sent = s. sendto(msg[ :BUFSIZE], (host, port)) msg = msg[bytes sent: ] sendto メソッドは実際に送信されたバイト数を返すため、各リトライは前回の送信終了ポイントから開始 され、また各データグラムで BUFSIZE を超えるオクテットが送信されないことが保証される。 データグラム (UDP) では分割送信したデータグラムが全て ( 又は「 1 つでも」 ) 受信される保証はなく、その 到着順序も保証されないことに注意されたい。こうした信頼性の問題を少しでも気にする場合は、このすべ てを保証し、舞台裏のごたごたまで良きに計らってくれる TCP コネクションの方が良いだろう。それでも私 はソケットデータグラムをデバッグに、特にアプリケーションが一台のマシンを超えて信頼できる IAN の範 囲におよぶ場合に ( のみに限って、ではない ) よく使う。 thon 標準ライプラリの logging モジュールも、オ プションでログの出力先として UDP をサポートしている。 参照 UDP データグラムによるネットワークオペレーションの典型的で有用な例として「レシピ 13.11 アクティ プでないコンピュータの検知」、標準ライプラリモジュール socket および logging についてのライプラリリファ

5. Pythonクックブック

] 2. ] 整形式 (well-fo 「 med) であるかチェックする ー 473 うことではない ) 。しかもすばやくしたい。 解法 SAX が ( 下で Expat のような高速パーサを使い ) これを行う高速かっシンプルな手段を供する。以下は整形 式チェックのスクリプトで、コマンドラインで指定した全ファイルを調べるものだ・ from xml. sax. handler import ContentHandler from xml. sax import make parser from g10b import glob import sys def parsefile(filename) : parser = make parser( ) parser. setContentHand1er(ContentHand1er( ) ) parser. parse(filename) f0 て arg in sys ・ argv[l:]: fo て filename in glob(arg) : try: parsefile(filename) print "%s is well-formed" % filename except Exception, e: print "%s is NOT well-formed! %s" % (filename, e) 考察 確実に言える場合には、 SAX の代わりに Expat を直接使うという選択もある。このアプローチを試すには関 フォーマンスの最後の一滴まで絞り出したい場合もあるだろう。 Expat がシステムにインストールしてあると みに絞って実行するからこそである。とはいえ、本当に膨大なファイル群の形式チェックを行うなど、パ る別の手続きだ。ここで示したスクリプトのパフォーマンスは極めて良いが、それは最小限のコアタスクの このレシピでは DTD やスキーマへの忠実性をチェックすることはしない。それは検証 ( validation ) と呼ばれ これは 1002 行目の 2 番目の文字にマッチングの取れないタグがあるという意味だ。 test. xml is NOT well-formed ! test. xml : 1002 : 2 : mismatched tag $ python wellformed. py test. xml た例外をすべて捕捉して以下のように出力する : レシピの関数 parsefile はドキュメント全体を解釈し、エラーがあれば例外を送出する。メイン部はこうし もっとも基本的な構文に従っているか知りたいだけだ。加工は不要であり、何もしないハンドラで十分だ。 書をパースするときは、 ContentHandler のインスタンスを文書内容の加工に使う。だがいまは文書が XML の このレシピでは、何もしないダミーの ContentHandle てから SAXAPI を使っている。一般に SAX で XML 文 れ、などなどに従ったものだ。 XML 宣言と単一のルート要素をもち、タグのすべてが正しく入れ子になっており、タグ属性は引用符に囲ま 整形式の XML 文書とは XML 文書の基本構文すべてにしたがうテキストのことだ。言い換えれば、正しい

6. Pythonクックブック

ロ . 1 1 複数の値を入れられる行 ( 「 (w) を持った Tkinte 「のリストボックス for 1 in self. lists: 1. insert(index, e[i]) = i + 1 1 def size(self) : return self. lists[o]. size( ) def see(self, index) : fo て 1 in self. lists: 1. see(index) def selection anchor(self, index) : fo て 1 in self. lists: 1. selection anchor(index) def selection clear(self, first, Iast=None) : fo て 1 in self. lists: 1. selection clear(first, last) def selection includes(self, index) : return self. lists[o]. selection includes(index) def selection set(self, first, last=None) : 1. selection set(first, last) for 1 in self. lists: ー 453 name maln tk = Tk( ) Label(tk, text='MultiListbox' ). pack( mlb = MuItiListbox(tk, (('Subject' f0 て i in て ange ( 100 の : mlb. insert(END, ('lmportant Message: %d' % i, mlb. pack(expand=YES, fill=BOTH) tk. mainloop( ) 考察 , ('Sender' 'John Do ざ ・ 10 / 10 / % 04d ' % ( 1900 + i ) ) ) , ('Date' , 10 ) ) ) これは複数のカラムを 1 つのスクロールバーで操作できるリストボックスで、 Tkinter の Listbox ウイジェッ トを複数組み合わせて作られた複合ウイジェットである。リストボックスの API は反映されているため、通 常のリストボックスと同じように動作するが、それぞれの行が複数の値を持つものとなっている。このウィ ジェットは軽快に動作し、利用も簡単である。欠点としてはテキストしかサポートしていないということが あげられるが、これは Listbox ウイジェットが根本的に持っている限界である。 このレシピではひとつだけの行しか選択できないように実装されているが、複数の行を選択するように拡 張することもできる。サイズ調整のできるカラムや、カラムのラベルをクリックすることでソートする機能 をつけるということも可能だ。リスト間の同期が壊れてしまうので、 Button -1 をドラッグしている間、自動的 にスクロールする機能ははずしている。しかし、 Button-2 でスクロールするという機能はしつかり動作する。 マウスのスクロールホイールは、プラットフォームによって動作が異なる。特定のプラットフォーム ( W ⅲ dowsXP など ) では動作するが、 X11 を利用しているプラットフォーム ( Linux など ) では動作しない。 X11

7. Pythonクックブック

] 章テキスト すべてにアクセスして再結合を行う。これらのアイテムは format 文字列中の marker で囲まれていた部分に他 ならないからだ。つまりこれらこそディクショナリで検索されるべき「マーキングされた部分文字列」なの である。 expand が format として受け入れる文字列は、 st ⅱ ng. Template の $ べースの文字列構文より柔軟である。マー カーも、たとえばダブルクオート門を format 文字列中で使いたい時は別のものが指定できる。識別子として マークする部分文字列に関しても制限がないので、 thon の式だって簡単に入れられるし (_getitem_ で eval を実行する d と一緒に使う ) 、他のあらゆる種類のプレースホルダーが使える。これだけでなく、ちょっと他 とは違った有用な効果もある : print expand('just "a" "'little"" test' one これは just one "little" test を出力する。高度なユーザは thon2.4 以降の string. Template クラスを継 承によりカスタマイズし、こうした全てを上回る機能が得られるが、それでもこちらの小さな expand 関数の 方が柔軟なやり方で簡単に使えるのである。 参照 ライプラリリファレンスの st ⅱ ng. Temp1ate ( thon2.4 以降 ) の解説、シーケンス ( 配列 ) 型の項 ( 文字列メソッ ド split および j0in 、それにスライシングについて ) 、ディクショナリの項 ( インデクシングおよび get メソッ ドについて ) 。 Python2.4 の string. Temp1ate クラスに関する更なる情報は「レシピ 1.17 文字列中の変数に手 を加える ( thon2.4 ) 」。 1 ゴ 7 文字列中の変数に手を加える ( Python2.4 以降 ) credit: John Nielsen, Lawrence ()luyede, Nick Coghlan 訳 : 石井寛、鴨澤眞夫 問題 文字列中の特別にマーキングした識別子をディクショナリの探索結果で置き換えて新しい文字列 # substitute にはキーワード引数を渡すこともできる : print new style. substitute({'thing':'test' } ) # 出力 : this is test # 出力 : this is 5 print new style. substitute({'thing ・ : 5 } ) # ディクショナリを引数に、 template の substitute メソッドを使用する : new style = string. Template('this is $thingl) # $ でマーキングした識別子をともなう文字列でテンプレートを作成する import string を示したコード片である : thon2.4 以降で新しく提供された st ⅱ ng. Template クラスはこのためにある。以下はこのクラスの使い方 解法 を得る、というのを Python2.4 以降で簡単にやりたい。

8. Pythonクックブック

ー ] 章テキスト afield = the1ine[3:8] データを特定のカラム数で分割すると考えるなら、一般にはリスト内包を使ったスライスが便利だ・ 28 fivers 文字列を個々のキャラクタにちょん切るのはもちろん簡単 : = [theline[k:k + 5] for k in xrange(), len(theline), 5 ) ] 5 バイトごとに分割するとする。これはスライスのリスト内包で簡単に書ける : 1 , sl, s2 = struct. unpack(baseformat, theline[ :struct. calcsize(baseformat)]) 「残り全部」を取らすに捨てる場合は、 theline の頭の方のみをアンパックすればよい・ 1 , sl, s2, t = struct. unpack(format, theline) format = "%s %ds" % (baseformat, numremain) # フォーマットを s フィールドで補ってからアンバック numremnn = len(theline) - struct. calcsize(baseformat) # struct. calcsize の方が一般性アリ ) を越える分のバイト数 # theline がべースフォーマットにの場合 24 バイトだが baseformat = "5s 3x 8s 8s" # 5 バイトの文字列を取って 3 バイトスキップし、 8 バイトの文字列を 2 っと、残り全部を取る : import struct フィールド長の見地から考える必要がある場合は、 struct. unpack が適切だろう。例を示す : cutS = [ 8 , 14 , 20 , 26 , 30 ] chars = list(theline) thon では取り出しやスキップのすべてで正しい長さを計算して入れてやらなければならない。取り出しの PerI の方が最後のフィールドのフィールド長に * を使えて「残り全部」を表せるので、少しリッチである。 は PerI の substr みたいなものだ。 Perl のビルトイン unpack と Python の struct. unpack は似たもの同士だが、 このレシピは「 PerI クックプック』の「レシピ 1.1 」にインスパイヤされたものだ。 python のスライシング 考察 て theline からスライスを得るだけのものだ。 と、最後の断点から文字列末尾までのスライスを得るべアがあるということだ。他の部分は、このペアを使っ ングで得るのに適切な ( i , j ) をもたらし、例外として文字列の頭から最初の断点までのスライスを得るべア (cuts[len(cuts)-l], None ) となる最後のペアである。言い換えれば、各ペアは断点と次の断点の間をスライシ この zip は (cuts[k], cuts [ k + (]) の形のペアをリストで返す。例外は ( 0 , ( uts [ (]) となる最初のペアと、 P1eces = [ theline[i:j] fo て i, j in zip([o] + cuts, cuts + [None]) ]

9. Pythonクックブック

1 章テキスト べてリジェクトされるはすだ。 「解法」でも推奨したが、ビルトイン関数 isinstan ( e を使う方がはるかに良い。ビルトイン型 basestring は まさにこのアプローチを可能にするために存在する。 basest ⅱ ng は str と uni ( ode で共通のべースクラスだし、 ユーザが文字列のように振る舞う型をコードにする場合には b a s e s t r i n g をベースクラスの 1 つにして isinstance テストが通るようにできる ( し、やっておくべきだ ) 。 basestring は 0bject 同様、本質的には「空」 の型であり、ゆえにこれをサプクラス化してもコストは発生しない。 だがしかし。 isinstance による正規的なチェックでは、明らかに「文字列のように振る舞う」オプジェクト である UserString クラス ( 標準ライプラリモジュール UserString のもの ) のインスタンスをアクセプトできな い。鳴呼 ! このクラスは basest ⅱ ng を継承してないのだ ! というわけで、この型をサポートするにはオ プジェクトが文字列のように振る舞うかを直接チェックしなければならない。たとえば以下のようにする : def isStringLike(anobj) : try: anobj + 、 except: return False else: return True この isStringLike 関数は「解法」で示した isAString 関数よりも遅いし複雑だが、 UserString( および他の、 文字列のように振る舞う型 ) のインスタンスを str や unicode のそれ同様にアクセプトする。 型チェックに対する均 rthon の一般アプローチはアヒル的型付け ( duck Ⅳ ping ) と呼ばれる。・アヒルのよう に歩き、アヒルのようにガーガー鳴くならオレたちには十分アヒルだ ' というやり方だ。レシピの isSt ⅱ ngLike 関数はガーガー鳴く部分だけでやっているが、おそらくこれで十分だ。オプジェクト anobj の文 字列的な特徴をさらにチェックしたい場合は、 try 節に少しリッチな式を使えばテストすべき特性を簡単に増 やせる。たとえば try 節を以下のようにする : try: anobj. lower( ) + anobj + ' とはいえ私の経験では、普通は isSt ⅱ ngLike 関数に示したシンプルなテストで満足できる。 型評価に対する ( というかホントはあらゆる評価に対する ) もっともパイソニックなアプローチは、やりた いタスクはなんでもやってしまい、状況がそれを許さない場合に出てくるであろうエラーや例外を検知して 処理するというものだ。このアプローチを「ゴメンナサイはオネガイシマスより楽 (" ⅳ seasiertoaskforg ⅳ e - ness than permission (EAFP)") 」という。 try/except は EAFP スタイルのキーツールだ 、でもやってい るように、きわめてリッチな特性群 ( たとえば文字列オプジェクトが可能にするあらゆるオペレーションやメ ソッドのすべて ) の代わりにシンプルなタスク ( たとえば空文字列との連結 ) が選択されることもある。 参照 ライプラリリファレンスおよび「巧 , thon クイックリファレンス』にある isinstance および basestring 両ビ ルトインについての解説。

10. Pythonクックブック

] 章 に留めたのは、 thon2.3 が関数オプジェクトの属性 fun ( name をリードオンリーと見なすためだ。こっした テキスト 適した iStr サプクラスを使った ( iList の ) サプクラスを作るのも簡単だ。クラスレベルメンバー wrap each item ちなみにこのお手本の iList クラスは間違いのないコーディングがしてあるので、特定アプリケーションに 保証しているにすぎない。あとはアイテム自身が自分で全部面倒を見るのだ。 基本的には iList のインスタンスに入る各アイテムが iStr のコールによってラップされる、ということを list. extend(self, map(self. wrap each item, seq)) def extend(self, seq) : list. append(self, self. wrap each_item(item)) def append(self, item) : setitem list. (self, i, v) else: v = self. wrap each item(v) if isinstance(), slice): v = map(self. wrap each item, v) def setitem (self, i, v) : = iStr wrap each item = self self[ : ] # setitem に頼って各アイテムを iStr でラップ list. init (self, *args) def init_(self, *args) : class iList(list) : に ) 大文字小文字無関係に扱うリストを作ってみせよう。割と簡単だ・ それでは iStr に基づいて、基本的に文字列であるアイテムを (count 、 index といったメソッドやソートの際 字小文字無関係なコンテナ型を作るなど、文字列ラッピングが必要なときにすぐ使えるということだ。 というのは、明らかに優れたアーキティクチャだ。つまりレシピのコードを道具箱に仕込んでおけば、大文 付くかもしれない。比較や検索で大文字小文字が無関係になるという機能を要素分割し、一度だけ実装する とこれを大文字小文字無関係であるかのように扱うコンテナーーを、いつのまにやら楽々作ってる自分に気 スト、セットなど、多種多様な「大文字小文字無関係の」コンテナ型ー一文字列型のキーやアイテムがある Macintosh のデフォルトファイルシステムとの互換を取ることなど、さまざまだ。また、ディクショナリ、リ 高い許容性を与えたり、ファイル名のマッチングにこの方法を使って、 Windows のファイルシステムや 大文字小文字無関係の ( しかしこれを保存する ) 文字列型にはたくさんの用途がある。ユーザ入力の解釈に 細かい事柄のせいで互換性を失うことを避けたのである。 較やハッシュに使われる特殊メソッドの項。 ライプラリリファレンスおよび fPython クイックリファレンス』の str 型および文字列メソッドの項、比 参照 をオーバーライドするだけでよいのである。