デコレーターに関する多くの記事を読んだにもかかわらず、デコレーターをよく理解するのに苦労しています ([this][1] SO で非常に人気のある記事を含む)。私は自分がバカに違いないのではないかと疑っていますが、バカであることに伴うすべての頑固さを考えて、これを理解しようと決心しました。
それ、そして私は良いユースケースを持っていると思います...
以下は、PDF ファイルからテキストを抽出する私のプロジェクトのコードです。処理には次の 3 つの手順が含まれます。
- PDF ファイルの処理に必要な PDFMiner オブジェクトをセットアップします (ボイラープレートの初期化)。
- PDF ファイルに処理関数を適用します。
- 何が起こっても、ファイルを閉じてください。
私は最近、コンテキスト マネージャーとwith
ステートメントについて学びましたが、これは彼らにとって良いユース ケースのように思えました。PDFMinerWrapper
そのため、クラスを定義することから始めました。
class PDFMinerWrapper(object):
'''
Usage:
with PDFWrapper('/path/to/file.pdf') as doc:
doc.dosomething()
'''
def __init__(self, pdf_doc, pdf_pwd=''):
self.pdf_doc = pdf_doc
self.pdf_pwd = pdf_pwd
def __enter__(self):
self.pdf = open(self.pdf_doc, 'rb')
parser = PDFParser(self.pdf) # create a parser object associated with the file object
doc = PDFDocument() # create a PDFDocument object that stores the document structure
parser.set_document(doc) # connect the parser and document objects
doc.set_parser(parser)
doc.initialize(self.pdf_pwd) # pass '' if no password required
return doc
def __exit__(self, type, value, traceback):
self.pdf.close()
# if we have an error, catch it, log it, and return the info
if isinstance(value, Exception):
self.logError()
print traceback
return value
これで、PDF ファイルを簡単に操作できるようになり、エラーが適切に処理されることを確認できるようになりました。理論的には、私がする必要があるのは次のようなことだけです:
with PDFMinerWrapper('/path/to/pdf') as doc:
foo(doc)
によって返されたオブジェクトに関数を適用する前に、PDF ドキュメントが抽出可能であることを確認する必要があることを除けば、これは素晴らしいことPDFMinerWrapper
です。私の現在の解決策には、中間ステップが含まれます。
私はPamplemousse
、PDFを操作するためのインターフェースとして機能するクラスを呼び出しています。次に、PDFMinerWrapper
オブジェクトがリンクされているファイルに対して操作を実行する必要があるたびに使用します。
以下は、その使用法を示す (要約された) コードです。
class Pamplemousse(object):
def __init__(self, inputfile, passwd='', enc='utf-8'):
self.pdf_doc = inputfile
self.passwd = passwd
self.enc = enc
def with_pdf(self, fn, *args):
result = None
with PDFMinerWrapper(self.pdf_doc, self.passwd) as doc:
if doc.is_extractable: # This is the test I need to perform
# apply function and return result
result = fn(doc, *args)
return result
def _parse_toc(self, doc):
toc = []
try:
toc = [(level, title) for level, title, dest, a, se in doc.get_outlines()]
except PDFNoOutlines:
pass
return toc
def get_toc(self):
return self.with_pdf(self._parse_toc)
PDF ファイルに対して操作を実行したいときはいつでも、関連する関数をwith_pdf
その引数とともにメソッドに渡します。次にwith_pdf
、メソッドはwith
ステートメントを使用してコンテキストマネージャーを活用しPDFMinerWrapper
(したがって、例外の適切な処理を保証します)、渡された関数を実際に適用する前にチェックを実行します。
私の質問は次のとおりです。
を明示的に呼び出す必要がないように、このコードを単純化したいと思いますPamplemousse.with_pdf
。私の理解では、デコレータがここで役立つ可能性があるため、次のようになります。
with
ステートメントを呼び出して抽出可能性チェックを実行するデコレータをどのように実装すればよいでしょうか?- デコレータをクラス メソッドにすることは可能ですか?それとも、デコレータを自由形式の関数またはクラスにする必要がありますか?