4

それぞれがファイルを操作する必要があるさまざまな関数を構築したいと思います。これをデコレータで実装しました。

もっとpythonicにできるかどうか教えてください:

def open_file(func):
    def a_wrapper(filename,separator,*args):
        f = open(filename,'w')
        return func(f,separator,*args)
    return a_wrapper

@open_file
def write_multiple_items(file, sep, *args):
    file.write(sep.join(args))

@open_file
def write_one_item(file,sep,name):
    file.write(sep.join(name))

write_multiple_items('foo.txt','--',"Hello","World", "!!!!")
write_one_item('bar.txt','--',"Bye World !!!")

ファイルを閉じる必要がありますか? どうやって?

4

2 に答える 2

4

with装飾された関数でのみファイルを使用することがわかっている場合は、ステートメントを使用することをお勧めします。また、separator実装の詳細です - 私はそれをラッパーから除外します:

def open_file(func):
    def a_wrapper(filename, *args):
        with open(filename, 'w') as f:
            return func(f, *args)
    return a_wrapper

また、@Platinum Azure が指摘しているようfunctools.wrapsに、デコレータ関数に使用することは常に良い考えです。これにより、ラップされた関数のメタデータがラッパー関数に存在することが保証されます (これは、関数をプログラム的にラップします)。

編集:

ラッパー関数から移動separatorする必要がある理由は、ファイル オブジェクトのみを取得する必要があり、区切り記号を必要としない他の関数がある可能性があるためです。次のような関数を作成する場合:

def say_hello(fp):
    fp.write("Hello World!")

に渡そうとするデコレータのバージョンを使用することはできません- それを試みると、1つの引数(ファイルオブジェクト)を2つの引数(ファイルオブジェクトとセパレーター。open_fileseparatorsay_helloTypeError

また、ラップされたすべての関数が少なくとも 1 つの追加引数を取る場合でも、区切り記号である必要はありません。これは、編集されていないデコレーターでもラップする正当な関数です。

def laugh(fp, number_of_times):
    fp.write("Ha! " * number_of_times)

separatorそれが実装の詳細であると私が言うときの意味です。理想的には、コードはドキュメントでもあります。このラッパーをセパレーターで分割されたデータを書き出すためにのみ使用する場合は、ラッパーの使用方法を文書化するのに役立つため、セパレーター引数をラッパーに残す必要があります。それ以外の場合、2 番目の引数は 14 番目の引数よりも重要ではなく、独自のパラメーターで呼び出すべきではありません。

于 2012-07-21T04:35:20.233 に答える
3

tryラッパー関数で/を使用finallyして、ファイルが閉じていることを確認するか、with十分に新しいバージョンの Python を使用している場合はステートメントを使用できます。

from functools import wraps
def open_file(func):
    @wraps(func)
    def a_wrapper(filename, sep, *args):
        f = open(filename, 'w')
        try:
            return func(f, sep, *args)
        finally:
            f.close()
    return a_wrapper

使用with:

from functools import wraps
def open_file(func):
    @wraps(func)
    def a_wrapper(filename, sep, *args):
        with open(filename, 'w') as f:
            return func(f, sep, *args)
    return a_wrapper
于 2012-07-21T04:34:32.293 に答える