2

私はまだPythonに比較的慣れておらず、1〜2年の独学で、コード構造を改善しようとしているので、書いた古いプログラムをリファクタリングしています。あるプログラムでは、ファイルを書き込むためのメソッドをいくつか定義しました。1 つ目は、"write" を使用して巨大な http 応答をダンプします。2 番目は、"writelines" を使用して、さまざまな派生リスト (リンクのリスト、フォーム、またはその他の抽出データなど) をダンプします。

私はもともとファイルの命名を考慮していました:

    @property
    def baseFilename(self):
        unacceptable = re.compile(r'\W+')
        fname = re.sub(unacceptable,'-',self.myUrl)
        t = datetime.datetime.now()
        dstring = "%s%s%s%s%s%s" % (t.year, t.month, t.day, t.hour, t.minute, t.second)
        fullname = fname + '_' + dstring + '.html'
        return fullname

しかし、各書き込みメソッドに大きな冗長コード ブロックがあります。

    def writeFile(self, someHtml, writeMethod=write, prefix="RESPONSE_"):
        '''The calling functions will supply only the data to be written and 
           static prefixes, e.g. "full_" for the entire http-response.
        '''

       fullpath = self.myDump + prefix + self.baseFilename
       with open(fullpath, 'w') as h:
           h.write(someHtml)
           h.close()
       print "saved %s" % fullpath
       return fullpath

    def writeList(self, someList, prefix="mechList_"):
        '''Like write file but for one of the many lists outputted.  
           How do I refactor this, since redundant?
        '''

        fullpath = self.myDump + prefix + self.baseFilename
        with open(fullpath, 'w') as h:
            h.writelines(someList)
            h.close()
        print "saved %s" % fullpath
        return fullpath

使用する書き込み方法を指定する変数を各関数に追加できるようにしたいと考えています (writeMethod=writelines など)。文字列を渡して、黒魔術関数の 1 つ (おそらく exec() だと思います) を使用することを検討しましたが、誰もそれらの関数を使用していないように見えるため、おそらく正しいとは言えません。この例全体は比較的ばかげているかもしれませんが、私はそれを回避することができたので、これらの種類のインスタンスメソッドを渡す方法を知っておくと役立つと判断しました (それは正しい用語ですか?)。これはバインドとバインド解除に関連していますか? 良い答えを得るために必要なのは、'write' や 'writelines' などを渡すために必要な構文だけです。ただし、追加の説明またはガイダンスが大好きです。ありがとう。

4

2 に答える 2

2

オブジェクトから「バインドされたメソッド」を取得できます。これは、オブジェクトへの参照がなくても関数として呼び出すことができます。

f = obj.method
f(args)
# is equivalent to
obj.method(args)

ただし、メソッドでのみ使用するオブジェクトを作成するため、これは役に立ちません。バインドされたメソッドとしてそこに渡すことはできません。の作成を除外できますがfullpath、これは冗長性の半分しか節約できません。私がやり過ぎだと思う1つのオプションは、書き込みに使用する関数を返すコールバックを渡すことです。

別のオプションは、すべての共通部分を除外し、残りをコールバックにプッシュするデコレーターです。これは装飾された関数です。

def uses_file(prefix_default):
    def decorator(f):
        @functools.wraps(f)
        def decorated(self, data, prefix=prefix_default):
            fullpath = obj.myDump + prefix + obj.baseFilename
            with open(fullpath, 'w') as h:
                f(h, data, prefix)
            print "saved", % fullpath
            return fullpath
        return decorated
    return decorator

# ...

@uses_file(default_prefix="RESPONE_")
def writeFile(self, someHtml, prefix):
   '''...'''
   h.write(someHtml)

@uses_file(default_prefix="mechList_")
def writeList(self, someList, prefix):
    '''...'''
    h.writelines(someList)
于 2011-04-27T12:17:58.567 に答える
1

たとえば、ラムダを使用するなど、これを行うにはさまざまな方法があります。

def writeFile(self, someHtml, writeMethod=lambda f, data: f.write(data), 
              prefix="RESPONSE_"):
    '''The calling functions will supply only the data to be written and 
       static prefixes, e.g. "full_" for the entire http-response.
    '''

   fullpath = self.myDump + prefix + self.baseFilename
   with open(fullpath, 'w') as h:
       writeMethod(h, someHtml)
       h.close()
   print "saved %s" % fullpath
   return fullpath
于 2011-04-27T12:17:56.350 に答える